diff --git a/OpenAL.cabal b/OpenAL.cabal
--- a/OpenAL.cabal
+++ b/OpenAL.cabal
@@ -1,79 +1,82 @@
 name: OpenAL
-version: 1.6.0.0
+version: 1.6.0.1
+synopsis: A binding to the OpenAL cross-platform 3D audio API
+description:
+  A Haskell binding for the OpenAL cross-platform 3D audio API,
+  appropriate for use with gaming applications and many other
+  types of audio applications.
+  .
+  On Windows, this package works well with the \"OpenAL Soft\" binary
+  distribution from <http://kcat.strangesoft.net/openal.html>.
+  Type \'cabal install --extra-lib-dirs=\<DIR\>\' where \<DIR\> is the
+  directory where libOpenAL32.dll.a is located (must be an absolute path).
+  Then rename soft_oal.dll to OpenAL32.dll and put it somewhere in
+  the PATH. I found that c:\\Windows\\ worked.
+  .
+  This package has also been tested on GNU/Linux and iOS.
+homepage: https://github.com/haskell-openal/ALUT
+bug-reports: https://github.com/haskell-openal/ALUT/issues
 license: BSD3
 license-file: LICENSE
-maintainer: Sven Panne <svenpanne@gmail.com>, Stephen Blackheath <haskell.openal.stephen@blacksapphire.com>
-bug-reports: https://github.com/haskell-openal/ALUT/issues
-homepage: https://github.com/haskell-openal/ALUT
+author: Sven Panne
+maintainer: Sven Panne <svenpanne@gmail.com>, Stephen Blackheath <haskell.openal2.stephen@blacksapphire.com>
 category: Sound
-synopsis: A binding to the OpenAL cross-platform 3D audio API
-description:
-        A Haskell binding for the OpenAL cross-platform 3D audio API,
-        appropriate for use with gaming applications and many other
-        types of audio applications.
-        .
-        On Windows, this package works well with the \"OpenAL Soft\" binary
-        distribution from <http://kcat.strangesoft.net/openal.html>. 
-        Type \'cabal install --extra-lib-dirs=\<DIR\>\' where \<DIR\> is the
-        directory where libOpenAL32.dll.a is located (must be an absolute path).
-        Then rename soft_oal.dll to OpenAL32.dll and put it somewhere in
-        the PATH. I found that c:\\Windows\\ worked.
-        .
-        This package has also been tested on GNU/Linux and iOS.
 build-type: Simple
-cabal-version:  >= 1.6
+cabal-version:  >= 1.10
 extra-source-files:
-        README.md
-        examples/test/TestDevice.hs
+  README.md
+  examples/test/TestDevice.hs
 
 flag UseNativeWindowsLibraries
-   description:
-      When compiling under Windows, use the native libraries instead of e.g. the
-      ones coming with Cygwin.
+  description:
+    When compiling under Windows, use the native libraries instead of e.g. the
+    ones coming with Cygwin.
 
 library
-    exposed-modules:
-            Sound.OpenAL,
-            Sound.OpenAL.AL,
-            Sound.OpenAL.AL.Attenuation,
-            Sound.OpenAL.AL.BasicTypes,
-            Sound.OpenAL.AL.Buffer,
-            Sound.OpenAL.AL.Doppler,
-            Sound.OpenAL.AL.Errors,
-            Sound.OpenAL.AL.Extensions,
-            Sound.OpenAL.AL.Listener,
-            Sound.OpenAL.AL.Source,
-            Sound.OpenAL.AL.StringQueries,
-            Sound.OpenAL.ALC,
-            Sound.OpenAL.ALC.BasicTypes,
-            Sound.OpenAL.ALC.Capture,
-            Sound.OpenAL.ALC.Context,
-            Sound.OpenAL.ALC.Device,
-            Sound.OpenAL.ALC.Errors,
-            Sound.OpenAL.ALC.Extensions
-    other-modules:
-            Sound.OpenAL.AL.ALboolean,
-            Sound.OpenAL.AL.BufferInternal,
-            Sound.OpenAL.AL.Format,
-            Sound.OpenAL.AL.PeekPoke,
-            Sound.OpenAL.AL.QueryUtils,
-            Sound.OpenAL.AL.SourceState,
-            Sound.OpenAL.AL.String,
-            Sound.OpenAL.ALC.ALCboolean,
-            Sound.OpenAL.ALC.QueryUtils,
-            Sound.OpenAL.ALC.String,
-            Sound.OpenAL.Config,
-            Sound.OpenAL.Constants
-    build-depends: base >= 3 && < 5, OpenGL >= 2.9.0.0
-    ghc-options: -Wall -O2
-    if os(windows) && flag(UseNativeWindowsLibraries)
-      extra-libraries: OpenAL32
+  exposed-modules:
+    Sound.OpenAL
+    Sound.OpenAL.AL
+    Sound.OpenAL.AL.Attenuation
+    Sound.OpenAL.AL.BasicTypes
+    Sound.OpenAL.AL.Buffer
+    Sound.OpenAL.AL.Doppler
+    Sound.OpenAL.AL.Errors
+    Sound.OpenAL.AL.Extensions
+    Sound.OpenAL.AL.Listener
+    Sound.OpenAL.AL.Source
+    Sound.OpenAL.AL.StringQueries
+    Sound.OpenAL.ALC
+    Sound.OpenAL.ALC.BasicTypes
+    Sound.OpenAL.ALC.Capture
+    Sound.OpenAL.ALC.Context
+    Sound.OpenAL.ALC.Device
+    Sound.OpenAL.ALC.Errors
+    Sound.OpenAL.ALC.Extensions
+  other-modules:
+    Sound.OpenAL.AL.ALboolean
+    Sound.OpenAL.AL.BufferInternal
+    Sound.OpenAL.AL.Format
+    Sound.OpenAL.AL.PeekPoke
+    Sound.OpenAL.AL.QueryUtils
+    Sound.OpenAL.AL.SourceState
+    Sound.OpenAL.AL.String
+    Sound.OpenAL.ALC.ALCboolean
+    Sound.OpenAL.ALC.QueryUtils
+    Sound.OpenAL.ALC.String
+    Sound.OpenAL.Config
+    Sound.OpenAL.Constants
+  hs-source-dirs: src
+  build-depends: base >= 3 && < 5, OpenGL >= 2.9.0.0
+  default-language: Haskell2010
+  ghc-options: -Wall -O2
+  if os(windows) && flag(UseNativeWindowsLibraries)
+    extra-libraries: OpenAL32
+  else
+    if os(darwin) || os(ios)
+      frameworks: OpenAL
     else
-      if os(darwin) || os(ios)
-        frameworks: OpenAL
-      else
-        extra-libraries: openal
+      extra-libraries: openal
 
 source-repository head
   type: git
-  location: https://github.com/haskell-openal/OpenAL
+  location: https://github.com/haskell-openal/OpenAL.git
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,1 +1,1 @@
-[![Build Status](https://travis-ci.org/haskell-openal/OpenAL.png)](https://travis-ci.org/haskell-openal/OpenAL)
+[![Hackage](https://img.shields.io/hackage/v/OpenAL.svg)](https://hackage.haskell.org/package/OpenAL) [![Build Status](https://travis-ci.org/haskell-openal/OpenAL.png)](https://travis-ci.org/haskell-openal/OpenAL)
diff --git a/Sound/OpenAL.hs b/Sound/OpenAL.hs
deleted file mode 100644
--- a/Sound/OpenAL.hs
+++ /dev/null
@@ -1,181 +0,0 @@
---------------------------------------------------------------------------------
--- |
--- Module      :  Sound.OpenAL
--- Copyright   :  (c) Sven Panne 2003-2013
--- License     :  BSD3
---
--- Maintainer  :  Sven Panne <svenpanne@gmail.com>
--- Stability   :  stable
--- Portability :  portable
---
--- A convenience module, combining the Haskell bindings for AL and ALC.
---
---------------------------------------------------------------------------------
-
-module Sound.OpenAL (
-   -- * A Brief History of OpenAL
-   -- $ABriefHistoryOfOpenAL
-
-   -- * What is the OpenAL Audio System?
-   -- $WhatIsTheOpenALAudioSystem
-
-   -- * Different Views of OpenAL
-
-   -- ** Programmer\'s View of OpenAL
-   -- $ProgrammersViewOfOpenAL
-
-   -- ** Implementor\'s View of OpenAL
-   -- $ImplementorsViewOfOpenAL
-
-   -- ** The Specification\'s View of OpenAL
-   -- $TheSpecificationsViewOfOpenAL
-
-   -- * Legal stuff
-   -- $LegalStuff
-
-     module Sound.OpenAL.AL
-   , module Sound.OpenAL.ALC
-
-   -- * Convenience Re-exports
-   , module Graphics.Rendering.OpenGL.GL.ObjectName
-   , module Graphics.Rendering.OpenGL.GL.StateVar
-   , module Graphics.Rendering.OpenGL.GL.Tensor
-) where
-
-import Sound.OpenAL.AL
-import Sound.OpenAL.ALC
-
-import Graphics.Rendering.OpenGL.GL.ObjectName
-import Graphics.Rendering.OpenGL.GL.StateVar
-import Graphics.Rendering.OpenGL.GL.Tensor ( Vector3(..), Vertex3(..) )
-
---------------------------------------------------------------------------------
--- $ABriefHistoryOfOpenAL
--- The first discussions about implementing OpenAL as an audio API complimentary
--- to OpenGL started around 1998. There were a few aborted attempts at creating
--- the headers and a specification, but by late 1999 Loki Entertainment Software
--- was in need for an API of exactly this type and pursued both a specification
--- and a Linux implementation. At around that time, Loki started talking with
--- Creative Labs about standardizing the API and expanding platform support. The
--- OpenAL 1.0 specification was released in early 2000 and compliant OpenAL
--- libraries were released in the same year for Linux, MacOS 8\/9, Windows, and
--- BeOS. Loki Entertainment also shipped several games using OpenAL in 2000:
--- Heavy Gear 2 and Heretic 2 (both under Linux). In 2001, Creative Labs
--- released the first hardware-accelerated OpenAL libraries. The libraries
--- supported the SoundBlaster Live on MacOS 8\/9 and Windows.
---
--- Since 2001, there has been continuous improvement in OpenAL. Some platforms
--- are less relevant than in 2000 (BeOS and MacOS 8\/9 for instance), but more
--- platforms have been added as well (BSD, Solaris, IRIX, Mac OS X, and the
--- popular console gaming platforms). Hardware support is enabled for many
--- Creative and NVIDIA audio devices under Windows as well.
---
--- In terms of product support, OpenAL has been used in a large number of titles
--- over the years, on many platforms (for a list of many of the titles, see
--- <http://www.openal.org/titles.html>).
-
---------------------------------------------------------------------------------
--- $WhatIsTheOpenALAudioSystem
--- OpenAL (for /Open Audio Library/) is a software interface to audio hardware.
--- The interface consists of a number of functions that allow a programmer to
--- specify the objects and operations in producing high-quality audio output,
--- specifically multichannel output of 3D arrangements of sound sources around a
--- listener.
---
--- The OpenAL API is designed to be cross-platform and easy to use. It resembles
--- the OpenGL API in coding style and conventions. OpenAL uses a syntax
--- resembling that of OpenGL where applicable. For more information on OpenGL,
--- see <http://www.opengl.org/> and the "Graphics.Rendering.OpenGL" module.
---
--- OpenAL is foremost a means to generate audio in a simulated three-dimensional
--- space.  Consequently, legacy audio concepts such as panning and left\/right
--- channels are not directly supported. OpenAL does include extensions
--- compatible with the IA-SIG 3D Level 1 and Level 2 rendering guidelines to
--- handle sound-source directivity and distancerelated attenuation and Doppler
--- effects, as well as environmental effects such as reflection, obstruction,
--- transmission, reverberation. For more information on IA-SIG 3D, see
--- <http://www.iasig.org/wg/closed/3dwg/3dwg.shtml>.
---
--- Like OpenGL, the OpenAL core API has no notion of an explicit rendering
--- context, and operates on an implied current OpenAL Context. Unlike the OpenGL
--- specification, the OpenAL specification includes both the core API (the
--- actual OpenAL API, see "Sound.OpenAL.AL") and the operating system bindings
--- of the ALC API (the /Audio Library Context/, see "Sound.OpenAL.ALC"). Unlike
--- OpenGL\'s GLX, WGL and other OS-specific bindings, the ALC API is portable
--- across platforms as well.
-
---------------------------------------------------------------------------------
--- $ProgrammersViewOfOpenAL
--- To the programmer, OpenAL is a set of commands that allow the specification
--- of sound sources and a listener in three dimensions, combined with commands
--- that control how these sound sources are rendered into the output buffer. The
--- effect of OpenAL commands is not guaranteed to be immediate, as there are
--- latencies depending on the implementation, but ideally such latency should
--- not be noticeable to the user.
---
--- A typical program that uses OpenAL begins with calls to open a sound device
--- which is used to process output and play it on attached hardware (speakers or
--- headphones). Then, calls are made to allocate an AL context and associate it
--- with the device. Once an AL context is allocated, the programmer is free to
--- issue AL commands. Some calls are used to render sources (point and
--- directional sources, looping or not), while others affect the rendering of
--- these sources including how they are attenuated by distance and relative
--- orientation.
-
---------------------------------------------------------------------------------
--- $ImplementorsViewOfOpenAL
--- To the implementor, OpenAL is a set of commands that affect the operation of
--- CPU and sound hardware. If the hardware consists only of an addressable
--- output buffer, then OpenAL must be implemented almost entirely on the host
--- CPU. In some cases audio hardware provides DSP-based and other acceleration
--- in various degrees. The OpenAL implementor\'s task is to provide the CPU
--- software interface while dividing the work for each AL command between the
--- CPU and the audio hardware. This division should be tailored to the available
--- audio hardware to obtain optimum performance in carrying out AL calls.
---
--- OpenAL maintains a considerable amount of state information. This state
--- controls how the sources are rendered into the output buffer. Some of this
--- state is directly available to the user: he or she can make calls to obtain
--- its value. Some of it, however, is visible only by the effect it has on what
--- is rendered. One of the main goals of the OpenAL specification is to make
--- OpenAL state information explicit, to elucidate how it changes, and to
--- indicate what its effects are.
-
---------------------------------------------------------------------------------
--- $TheSpecificationsViewOfOpenAL
--- The OpenAL specification (see <http://www.openal.org/documentation.html>)
--- views OpenAL as a state machine that controls a multichannel processing
--- system to synthesize a digital stream, passing sample data through a chain of
--- parametrized digital audio signal processing operations. This model should
--- engender a specification that satisfies the needs of both programmers and
--- implementors. It does not, however, necessarily provide a model for
--- implementation. Any proper implementation must produce results conforming to
--- those produced by the methods specified in the OpenAL specification, but
--- there may be ways to carry out a particular computation that are more
--- efficient than the one specified.
-
---------------------------------------------------------------------------------
--- $LegalStuff
--- The documentation is more or less based upon the OpenAL 1.1 Specification and
--- Reference, which is in turn based upon the older OpenAL Specification and
--- Reference (1.0), published in June 2000. Both copyright notices are presented
--- below:
---
--- Version 1.1: Published June 2005, Copyright (c) 2005 by authors
---
--- Version 1.0 Draft Edition: Published June 2000, Copyright (c) 1999-2000 by
--- Loki Software
---
--- Permission is granted to make and distribute verbatim copies of this manual
--- provided the copyright notice and this permission notice are preserved on all
--- copies.  Permission is granted to copy and distribute translations of this
--- manual into another language, under the above conditions for modified
--- versions, except that this permission notice may be stated in a translation
--- approved by the copyright owners.
---
--- BeOS is a trademark of PalmSource, Inc. Linux is a trademark of Linus
--- Torvalds. Macintosh and Apple are trademarks of Apple Computer, Inc. OpenAL
--- is a trademark of Creative Labs, Inc. OpenGL is a trademark of Silicon
--- Graphics, Inc. UNIX is a trademark of X\/Open Group. Windows is a trademark
--- of Microsoft Corp. X Window System is a trademark of X Consortium, Inc. All
--- other trademarks are property of their respective owners.
diff --git a/Sound/OpenAL/AL.hs b/Sound/OpenAL/AL.hs
deleted file mode 100644
--- a/Sound/OpenAL/AL.hs
+++ /dev/null
@@ -1,128 +0,0 @@
---------------------------------------------------------------------------------
--- |
--- Module      :  Sound.OpenAL.AL
--- Copyright   :  (c) Sven Panne 2003-2013
--- License     :  BSD3
--- 
--- Maintainer  :  Sven Panne <svenpanne@gmail.com>
--- Stability   :  stable
--- Portability :  portable
---
--- This module corresponds to chapters 2 (OpenAL Operation), 3 (State and State
--- Requests), 4 (Listener and Sources) and 5 (Buffers) of the OpenAL
--- Specification and Reference (version 1.1).
---
---------------------------------------------------------------------------------
-
-module Sound.OpenAL.AL (
-   -- * OpenAL Fundamentals
-   -- $OpenALFundamentals
-
-   -- * Basic AL Operation
-   -- $BasicALOperation
-
-   -- * Time and Frequency
-   -- $TimeAndFrequency
-
-   -- * Space and Distance
-   -- $SpaceAndDistance
-
-   -- * Coordinate System
-   -- $CoordinateSystem
-
-   module Sound.OpenAL.AL.BasicTypes,
-   module Sound.OpenAL.AL.Errors,
-   module Sound.OpenAL.AL.StringQueries,
-   module Sound.OpenAL.AL.Attenuation,
-   module Sound.OpenAL.AL.Doppler,
-   module Sound.OpenAL.AL.Listener,
-   module Sound.OpenAL.AL.Source,
-   module Sound.OpenAL.AL.Buffer,
-   module Sound.OpenAL.AL.Extensions
-) where
-
-import Sound.OpenAL.AL.BasicTypes
-import Sound.OpenAL.AL.Errors
-import Sound.OpenAL.AL.StringQueries
-import Sound.OpenAL.AL.Attenuation
-import Sound.OpenAL.AL.Doppler
-import Sound.OpenAL.AL.Listener
-import Sound.OpenAL.AL.Source
-import Sound.OpenAL.AL.Buffer
-import Sound.OpenAL.AL.Extensions
-
---------------------------------------------------------------------------------
--- $OpenALFundamentals
--- OpenAL is concerned with rendering audio into an output buffer and collecting
--- audio data from an input buffer. OpenAL\'s primary use is assumed to be for
--- spatialized audio. There is no support for MIDI.
---
--- OpenAL has three fundamental primitives or objects: 'Buffer's, 'Source's, and
--- a single listener (see "Sound.OpenAL.AL.Listener"). Each object can be
--- changed independently; the setting of one object does not affect the setting
--- of others. The application can also set modes that affect processing. Modes
--- are set, objects specified, and other OpenAL operations performed by sending
--- commands in the form of function or procedure calls.
---
--- Sources store locations, directions, and other attributes of an object in 3D
--- space and have a buffer associated with them for playback. When the program
--- wants to play a sound, it controls execution through a source object. Sources
--- are processed independently from each other.
---
--- Buffers store compressed or uncompressed audio data. It is common to
--- initialize a large set of buffers when the program first starts (or at
--- non-critical times during execution, between levels in a game, for
--- instance). Buffers are referred to by sources. Data (audio sample data) is
--- associated with buffers.
---
--- There is only one listener (per audio context). The listener attributes are
--- similar to source attributes, but are used to represent where the user is
--- hearing the audio from. The influence of all the sources from the perspective
--- of the listener is mixed and played for the user.
-
---------------------------------------------------------------------------------
--- $BasicALOperation
--- OpenAL can be used for a variety of audio playback tasks, and is an excellent
--- complement to OpenGL for real-time rendering, see
--- "Graphics.Rendering.OpenGL". A programmer who is familiar with OpenGL will
--- immediately notice the similarities between the two APIs in that they
--- describe their 3D environments using similar methods.
--- 
--- For an OpenGL\/OpenAL program, most of the audio programming will be in two
--- places in the code: initialization of the program, and the rendering loop. An
--- OpenGL\/OpenAL program will typically contain a section where the graphics
--- and audio systems are initialized, although it may be spread into multiple
--- functions. For OpenAL, initialization normally consists of creating a
--- context, creating the initial set of buffers, loading the buffers with sample
--- data, creating sources, attaching buffers to sources, setting locations and
--- directions for the listener and sources, and setting the initial values for
--- state global to OpenAL.
-
---------------------------------------------------------------------------------
--- $TimeAndFrequency
--- By default, OpenAL uses seconds and Hertz as units for time and frequency,
--- respectively. A float or integral value of one for a variable that specifies
--- quantities like duration, latency, delay, or any other parameter measured as
--- time, specifies 1 second. For frequency, the basic unit is 1\/second, or
--- Hertz. In other words, sample frequencies and frequency cut-offs or filter
--- parameters specifying frequencies are expressed in units of Hertz.
-
---------------------------------------------------------------------------------
--- $SpaceAndDistance
--- OpenAL does not define the units of measurement for distances. The
--- application is free to use meters, inches, or parsecs. OpenAL provides means
--- for simulating the natural attenuation of sound according to distance, and to
--- exaggerate or reduce this effect.  However, the resulting effects do not
--- depend on the distance unit used by the application to express source and
--- listener coordinates. OpenAL calculations are scale invariant.  The
--- specification assumes Euclidean calculation of distances, and mandates that
--- if two sources are sorted with respect to the Euclidean metric, the distance
--- calculation used by the implementation has to preserve that order.
-
---------------------------------------------------------------------------------
--- $CoordinateSystem
--- OpenAL - like OpenGL - uses a right-handed Cartesian coordinate system (RHS),
--- where in a frontal default view X (thumb) points right, Y (index finger)
--- points up, and Z (middle finger) points towards the viewer\/camera. To switch
--- from a left handed coordinate system (LHS) to a right handed coordinate
--- systems, flip the sign on the Z coordinate.
diff --git a/Sound/OpenAL/AL/ALboolean.hs b/Sound/OpenAL/AL/ALboolean.hs
deleted file mode 100644
--- a/Sound/OpenAL/AL/ALboolean.hs
+++ /dev/null
@@ -1,30 +0,0 @@
-{-# OPTIONS_HADDOCK hide #-}
---------------------------------------------------------------------------------
--- |
--- Module      :  Sound.OpenAL.AL.ALboolean
--- Copyright   :  (c) Sven Panne 2003-2013
--- License     :  BSD3
--- 
--- Maintainer  :  Sven Panne <svenpanne@gmail.com>
--- Stability   :  stable
--- Portability :  portable
---
--- This is a purely internal module for (un-)marshaling ALboolean.
---
---------------------------------------------------------------------------------
-
-module Sound.OpenAL.AL.ALboolean (
-   marshalALboolean, unmarshalALboolean
-) where
-
-import Sound.OpenAL.AL.BasicTypes ( ALboolean )
-import Sound.OpenAL.Constants ( al_FALSE, al_TRUE )
-
---------------------------------------------------------------------------------
-
-marshalALboolean :: Bool -> ALboolean
-marshalALboolean False = al_FALSE
-marshalALboolean True  = al_TRUE
-
-unmarshalALboolean :: ALboolean -> Bool
-unmarshalALboolean = (/= al_FALSE)
diff --git a/Sound/OpenAL/AL/Attenuation.hs b/Sound/OpenAL/AL/Attenuation.hs
deleted file mode 100644
--- a/Sound/OpenAL/AL/Attenuation.hs
+++ /dev/null
@@ -1,207 +0,0 @@
-{-# LANGUAGE ForeignFunctionInterface #-}
-{-# OPTIONS_GHC -fno-warn-unused-imports #-}
---------------------------------------------------------------------------------
--- |
--- Module      :  Sound.OpenAL.AL.Attenuation
--- Copyright   :  (c) Sven Panne 2003-2013
--- License     :  BSD3
--- 
--- Maintainer  :  Sven Panne <svenpanne@gmail.com>
--- Stability   :  stable
--- Portability :  portable
---
--- This module corresponds to section 3.4 (Attenuation By Distance) of the
--- OpenAL Specification and Reference (version 1.1).
--- 
---------------------------------------------------------------------------------
-
-module Sound.OpenAL.AL.Attenuation (
-   -- * Introduction
-   -- $Introduction
-
-   -- * Handling the Distance Model
-   DistanceModel(..), distanceModel
-
-   -- * Evaluation of Gain\/Attenuation Related State
-   -- $EvaluationOfGainAttenuationRelatedState
-
-   -- * No Culling By Distance
-   -- $NoCullingByDistance
-) where
-
-import Foreign.C.Types
-import Foreign.Marshal.Alloc
-import Foreign.Ptr
-import Graphics.Rendering.OpenGL.GL.StateVar
-import Sound.OpenAL.AL.BasicTypes
-import Sound.OpenAL.AL.PeekPoke
-import Sound.OpenAL.AL.QueryUtils
-import Sound.OpenAL.Constants
-
--- For Haddock only.
-import Sound.OpenAL.AL.Source
-
---------------------------------------------------------------------------------
--- $Introduction
--- Samples usually use the entire dynamic range of the chosen format\/encoding,
--- independent of their real world intensity. In other words, a jet engine and a
--- clockwork both will have samples with full amplitude. The application will
--- then have to adjust source gain accordingly to account for relative
--- differences.
--- 
--- Source gain is then attenuated by distance. The effective attenuation of a
--- source depends on many factors, among which distance attenuation and source
--- and listener gain are only some of the contributing factors. Even if the
--- source and listener gain exceed 1 (amplification beyond the guaranteed
--- dynamic range), distance and other attenuation might ultimately limit the
--- overall gain to a value below 1.
-
---------------------------------------------------------------------------------
--- $EvaluationOfGainAttenuationRelatedState
--- While amplification\/attenuation commute (multiplication of scaling factors),
--- clamping operations do not. The order in which various gain related
--- operations are applied is:
--- 
--- 1. Distance attenuation is calculated first, including minimum
--- ('referenceDistance') and maximum ('maxDistance') thresholds.
--- 
--- 2. The result is then multiplied by source gain.
--- 
--- 3. If the source is directional (the inner cone angle is less than the outer
--- cone angle, see 'coneAngles'), an angle-dependent attenuation is calculated
--- depending on 'coneOuterGain', and multiplied with the distance-dependent
--- attenuation. The resulting attenuation factor for the given angle and
--- distance between listener and source is multiplied with 'sourceGain'.
--- 
--- 4. The effective gain computed this way is compared against 'gainBounds'.
--- 
--- 5. The result is guaranteed to be clamped to 'gainBounds', and subsequently
--- multiplied by listener gain which serves as an overall volume control.
--- 
--- The implementation is free to clamp listener gain if necessary due to
--- hardware or implementation constraints.
-
---------------------------------------------------------------------------------
--- $NoCullingByDistance
--- With the DS3D compatible inverse clamped distance model, OpenAL provides a
--- per-source 'maxDistance' attribute that can be used to define a distance
--- beyond which the source will not be further attenuated by distance. The DS3D
--- distance attenuation model and its clamping of volume is also extended by a
--- mechanism to cull (mute) sources from processing, based on distance. However,
--- the OpenAL does not support culling a source from processing based on a
--- distance threshold.
--- 
--- At this time OpenAL is not meant to support culling at all. Culling based on
--- distance, or bounding volumes, or other criteria, is best left to the
--- application. For example, the application might employ sophisticated
--- techniques to determine whether sources are audible that are beyond the scope
--- of OpenAL. In particular, rule based culling inevitably introduces acoustic
--- artifacts. E.g. if the listener-source distance is nearly equal to the culling
--- threshold distance, but varies above and below, there will be popping
--- artifacts in the absence of hysteresis.
-
---------------------------------------------------------------------------------
-
--- | OpenAL currently supports six modes of operation with respect to distance
--- attenuation, including one that is similar to the IASIG I3DL2 model. The
--- application chooses one of these models (or chooses to disable
--- distance-dependent attenuation) on a per-context basis.
---
--- The distance used in the formulas for the \"clamped\" modes below is clamped
--- to be in the range between 'referenceDistance' and 'maxDistance':
---
--- /clamped distance/ =
---    max('referenceDistance', min(/distance/, 'maxDistance'))
---
--- The linear models are not physically realistic, but do allow full attenuation
--- of a source beyond a specified distance. The OpenAL implementation is still
--- free to apply any range clamping as necessary.
--- 
--- With all the distance models, if the formula can not be evaluated then the
--- source will not be attenuated. For example, if a linear model is being used
--- with 'referenceDistance' equal to 'maxDistance', then the gain equation will
--- have a divide-by-zero error in it. In this case, there is no attenuation for
--- that source.
-
-data DistanceModel =
-     NoAttenuation
-   -- ^ Bypass all distance attenuation calculation for all sources. The
-   --   implementation is expected to optimize this situation.
-   | InverseDistance
-   -- ^ Inverse distance rolloff model, which is equivalent to the IASIG I3DL2
-   --   model with the exception that 'referenceDistance' does not imply any
-   --   clamping.
-   --
-   --   /gain/ = 'referenceDistance' \/ ('referenceDistance' +
-   --             'rolloffFactor' \* (/distance/ - 'referenceDistance'))
-   --
-   --   The 'referenceDistance' parameter used here is a per-source attribute
-   --   which is the distance at which the listener will experience gain
-   --   (unless the implementation had to clamp effective gain to the available
-   --   dynamic range). 'rolloffFactor' is per-source parameter the application
-   --   can use to increase or decrease the range of a source by decreasing or
-   --   increasing the attenuation, respectively. The default value is 1. The
-   --   implementation is free to optimize for a 'rolloffFactor' value of 0,
-   --   which indicates that the application does not wish any distance
-   --   attenuation on the respective source.
-   | InverseDistanceClamped
-   -- ^ Inverse Distance clamped model, which is essentially the inverse
-   --   distance rolloff model, extended to guarantee that for distances below
-   --   'referenceDistance', gain is clamped. This mode is equivalent to the
-   --   IASIG I3DL2 distance model.
-   | LinearDistance
-   -- ^ Linear distance rolloff model, modeling a linear dropoff in gain as
-   -- distance increases between the source and listener.
-   --
-   --   /gain/ = (1 - 'rolloffFactor' \* (/distance/ - 'referenceDistance') \/
-   --            ('maxDistance' - 'referenceDistance'))
-   | LinearDistanceClamped
-   -- ^ Linear Distance clamped model, which is the linear model, extended to
-   --   guarantee that for distances below 'referenceDistance', gain is clamped.
-   | ExponentDistance
-   -- ^ Exponential distance rolloff model, modeling an exponential dropoff in
-   --   gain as distance increases between the source and listener.
-   --
-   --   /gain/ = (/distance/ \/ 'referenceDistance') \*\* (- 'rolloffFactor')
-   | ExponentDistanceClamped
-   -- ^ Exponential Distance clamped model, which is the exponential model,
-   --   extended to guarantee that for distances below 'referenceDistance',
-   --   gain is clamped.
-   deriving ( Eq, Ord, Show )
-
-marshalDistanceModel :: DistanceModel -> ALenum
-marshalDistanceModel x = case x of
-   NoAttenuation -> al_NONE
-   InverseDistance -> al_INVERSE_DISTANCE
-   InverseDistanceClamped -> al_INVERSE_DISTANCE_CLAMPED
-   LinearDistance -> al_LINEAR_DISTANCE
-   LinearDistanceClamped -> al_LINEAR_DISTANCE_CLAMPED
-   ExponentDistance -> al_EXPONENT_DISTANCE
-   ExponentDistanceClamped -> al_EXPONENT_DISTANCE_CLAMPED
-
-unmarshalDistanceModel :: ALenum -> DistanceModel
-unmarshalDistanceModel x
-   | x == al_NONE = NoAttenuation
-   | x == al_INVERSE_DISTANCE = InverseDistance
-   | x == al_INVERSE_DISTANCE_CLAMPED = InverseDistanceClamped
-   | x == al_LINEAR_DISTANCE = LinearDistance
-   | x == al_LINEAR_DISTANCE_CLAMPED = LinearDistanceClamped
-   | x == al_EXPONENT_DISTANCE = ExponentDistance
-   | x == al_EXPONENT_DISTANCE_CLAMPED = ExponentDistanceClamped
-   | otherwise = error ("unmarshalDistanceModel: illegal value " ++ show x)
-
--- | Contains the current per-context distance model.
-
-distanceModel :: StateVar DistanceModel
-distanceModel =
-   makeStateVar
-      (alloca $ \buf -> do
-          alGetIntegerv (marshalGetPName GetDistanceModel) buf
-          peek1 (unmarshalDistanceModel . fromIntegral) buf)
-      (alDistanceModel . marshalDistanceModel)
-
-foreign import ccall unsafe "alGetIntegerv"
-   alGetIntegerv :: ALenum -> Ptr ALint -> IO ()
-
-foreign import ccall unsafe "alDistanceModel"
-   alDistanceModel :: ALenum -> IO ()
diff --git a/Sound/OpenAL/AL/BasicTypes.hs b/Sound/OpenAL/AL/BasicTypes.hs
deleted file mode 100644
--- a/Sound/OpenAL/AL/BasicTypes.hs
+++ /dev/null
@@ -1,49 +0,0 @@
---------------------------------------------------------------------------------
--- |
--- Module      :  Sound.OpenAL.AL.BasicTypes
--- Copyright   :  (c) Sven Panne 2003-2013
--- License     :  BSD3
--- 
--- Maintainer  :  Sven Panne <svenpanne@gmail.com>
--- Stability   :  stable
--- Portability :  portable
---
--- This module corresponds to section 2.2 (Primitive Types) of the OpenAL
--- Specification and Reference (version 1.1).
---
---------------------------------------------------------------------------------
-
-module Sound.OpenAL.AL.BasicTypes (
-   -- * Primitive Types
-   -- $PrimitiveTypes
-
-   -- * Floating-Point Computation
-   -- $FloatingPointComputation
-
-   ALboolean, ALchar, ALbyte, ALubyte, ALshort, ALushort, ALint, ALuint,
-   ALsizei, ALenum, ALfloat, ALdouble
-) where
-
-import Sound.OpenAL.Config
-
---------------------------------------------------------------------------------
--- $PrimitiveTypes
--- As OpenAL is meant to allow for seamless integration with OpenGL code if
--- needed, the OpenAL library primitive (scalar) data types mimic the OpenGL
--- data types. Guaranteed minimum sizes are stated for OpenGL data types, but
--- the actual choice of C data type is left to the implementation. All
--- implementations on a given binary architecture, however, must use a common
--- definition of these data types.
- 
---------------------------------------------------------------------------------
--- $FloatingPointComputation
--- Any representable floating-point value is legal as input to an OpenAL command
--- that requires floating point data. The result of providing a value that is
--- not a floating point number to such a command is unspecified, but must not
--- lead to OpenAL being interrupted or terminated. In IEEE arithmetic, for
--- example, providing a negative zero or a denormalized number to an OpenAL
--- command yields predictable results, while providing a NaN or infinity yields
--- unspecified results.  Some calculations require division. In such cases
--- (including implied divisions required by vector normalizations), a division
--- by zero produces an unspecified result but must not lead to OpenAL
--- interruption or termination.
diff --git a/Sound/OpenAL/AL/Buffer.hs b/Sound/OpenAL/AL/Buffer.hs
deleted file mode 100644
--- a/Sound/OpenAL/AL/Buffer.hs
+++ /dev/null
@@ -1,170 +0,0 @@
-{-# LANGUAGE ForeignFunctionInterface #-}
-{-# OPTIONS_GHC -fno-warn-unused-imports #-}
---------------------------------------------------------------------------------
--- |
--- Module      :  Sound.OpenAL.AL.Buffer
--- Copyright   :  (c) Sven Panne 2003-2013
--- License     :  BSD3
--- 
--- Maintainer  :  Sven Panne <svenpanne@gmail.com>
--- Stability   :  stable
--- Portability :  portable
---
--- This module corresponds to chapter 6 (Buffers) of the OpenAL Specification
--- and Reference (version 1.1).
---
--- A buffer encapsulates OpenAL state related to storing sample data. The
--- application can request and release buffer objects, and fill them with
--- data. Data can be supplied compressed and encoded as long as the format is
--- supported. Buffers can, internally, contain waveform data as uncompressed or
--- compressed samples.
--- 
--- Unlike source (see "Sound.OpenAL.AL.Source") and listener (see
--- "Sound.OpenAL.AL.Listener") objects, buffer objects can be shared among AL
--- contexts. Buffers are referenced by sources. A single buffer can be referred
--- to by multiple sources. This separation allows drivers and hardware to
--- optimize storage and processing where applicable.
--- 
--- The simplest supported format for buffer data is PCM. PCM data is assumed to
--- use the processor\'s native byte order. Other formats use the byte order
--- native to that format.
--- 
--- At this time, buffer states are defined for purposes of discussion. The
--- states described in this section are not exposed through the API (can not be
--- queried, or be set directly), and the state description used in the
--- implementation might differ from this.
---
--- A buffer is considered to be in one of the following states, with respect to
--- all sources:
---
--- [/unused/] The buffer is not included in any queue for any source. In
--- particular, the buffer is neither pending nor current for any source. The
--- buffer name can be deleted at this time.
---
--- [/processed/] The buffer is listed in the queue of at least one source, but
--- is neither pending nor current for any source. The buffer can be deleted as
--- soon as it has been unqueued for all sources it is queued with.
---
--- [/pending/] There is at least one source for which the buffer has been queued,
--- for which the buffer data has not yet been dereferenced. The buffer can only
--- be unqueued for those sources that have dereferenced the data in the buffer
--- in its entirety, and cannot be deleted or changed.
---
--- The buffer state is dependent on the state of all sources that is has been
--- queued for. A single queue occurrence of a buffer propagates the buffer state
--- (over all sources) from /unused/ to /processed/ or higher. Sources that are
--- in the 'Stopped' or 'Initial' states still have queue entries that cause
--- buffers to be /processed/.
--- 
--- A single queue entry with a single source for which the buffer is not yet
--- /processed/ propagates the buffer\'s queuing state to /pending/.
--- 
--- Buffers that are /processed/ for a given source can be unqueued from that
--- source\'s queue. Buffers that have been unqueued from all sources are
--- /unused/. Buffers that are /unused/ can be deleted, or changed by writing
--- 'bufferData'.
---
---------------------------------------------------------------------------------
-
-module Sound.OpenAL.AL.Buffer (
-   Buffer, MemoryRegion(..), Format(..), BufferData(..), bufferData
-) where
-
-import Foreign.C.Types
-import Foreign.Marshal.Alloc
-import Foreign.Ptr
-import Graphics.Rendering.OpenGL.GL.StateVar
-import Sound.OpenAL.AL.BasicTypes
-import Sound.OpenAL.AL.BufferInternal
-import Sound.OpenAL.AL.Format
-import Sound.OpenAL.AL.PeekPoke
-import Sound.OpenAL.ALC.Context ( Frequency )
-import Sound.OpenAL.Constants
-
--- For Haddock only.
-import Sound.OpenAL.AL.Errors
-import Sound.OpenAL.AL.SourceState
-
---------------------------------------------------------------------------------
-
-data MemoryRegion a = MemoryRegion (Ptr a) ALsizei
-   deriving ( Eq, Ord, Show )
-
-data BufferData a = BufferData (MemoryRegion a) Format Frequency
-   deriving ( Eq, Ord, Show )
-
---------------------------------------------------------------------------------
-
--- | A special case of buffer state is the actual sound sample data stored in
--- association with the buffer. Applications can specify sample data using
--- 'bufferData'.
---
--- The data specified is copied to an internal software, or if possible,
--- hardware buffer. The implementation is free to apply decompression,
--- conversion, resampling, and filtering as needed. The internal format of the
--- buffer is not exposed to the application, and not accessible.
---
--- Buffers containing audio data with more than one channel will be played
--- without 3D spatialization features, these formats are normally used for
--- background music. Applications should always check for an error condition
--- after attempting to specify buffer data in case an implementation has to
--- generate an 'ALOutOfMemory' or a conversion related 'ALInvalidValue' error.
--- The application is free to reuse the memory specified by the data pointer
--- once 'bufferData' is set. The implementation has to dereference, e.g. copy,
--- the data while accessing 'bufferData' execution.
-
-bufferData :: Buffer -> StateVar (BufferData a)
-bufferData buffer = makeStateVar (getBufferData buffer) (setBufferData buffer)
-
-getBufferData :: Buffer -> IO (BufferData a)
-getBufferData buffer = do
-   channels <- getBufferi buffer Channels
-   bits <- getBufferi buffer Bits
-   raw <- return nullPtr -- ToDo: AL_DATA query missing!!!
-   size <- getBufferi buffer Size
-   frequency <- getBufferi buffer Frequency
-   return $ BufferData (MemoryRegion  raw size) (makeFormat channels bits) frequency
-
-setBufferData :: Buffer -> BufferData a -> IO ()
-setBufferData buffer (BufferData (MemoryRegion raw size) format frequency) =
-      alBufferData buffer (marshalFormat format) raw size (round frequency)
-
-foreign import ccall unsafe "alBufferData"
-   alBufferData :: Buffer -> ALenum -> Ptr a -> ALsizei -> ALsizei -> IO ()
-
---------------------------------------------------------------------------------
-
--- ToDo: What about IMAADPCMMono16, IMAADPCMStereo16, Vorbis...?
-makeFormat :: ALint -> ALint -> Format
-makeFormat 1  8 = Mono8
-makeFormat 2  8 = Stereo8
-makeFormat 1 16 = Mono16
-makeFormat 2 16 = Stereo16
-makeFormat channels bits =
-   error ("makeFormat: illegal values " ++ show (channels, bits))
-
---------------------------------------------------------------------------------
-
-data BufferQuery =
-     Frequency
-   | Size
-   | Bits
-   | Channels
-
-marshalBufferQuery :: BufferQuery -> ALenum
-marshalBufferQuery x = case x of
-   Frequency -> al_FREQUENCY
-   Size -> al_SIZE
-   Bits -> al_BITS
-   Channels -> al_CHANNELS
-
---------------------------------------------------------------------------------
-
-getBufferi :: Num a => Buffer -> BufferQuery -> IO a
-getBufferi buffer query =
-   alloca $ \buf -> do
-      alGetBufferi buffer (marshalBufferQuery query) buf
-      peek1 fromIntegral buf
-
-foreign import ccall unsafe "alGetBufferi"
-   alGetBufferi :: Buffer -> ALenum -> Ptr ALint -> IO ()
diff --git a/Sound/OpenAL/AL/BufferInternal.hs b/Sound/OpenAL/AL/BufferInternal.hs
deleted file mode 100644
--- a/Sound/OpenAL/AL/BufferInternal.hs
+++ /dev/null
@@ -1,78 +0,0 @@
-{-# LANGUAGE ForeignFunctionInterface #-}
-{-# OPTIONS_HADDOCK hide #-}
---------------------------------------------------------------------------------
--- |
--- Module      :  Sound.OpenAL.AL.BufferInternal
--- Copyright   :  (c) Sven Panne 2003-2013
--- License     :  BSD3
--- 
--- Maintainer  :  Sven Panne <svenpanne@gmail.com>
--- Stability   :  stable
--- Portability :  portable
---
--- This is a purely internal module for (un-)marshaling Buffer.
---
---------------------------------------------------------------------------------
-
-module Sound.OpenAL.AL.BufferInternal (
-   Buffer(..), marshalBuffer, unmarshalBuffer
-) where
-
-import Graphics.Rendering.OpenGL.GL.ObjectName
-import Foreign.Marshal.Array ( withArrayLen, peekArray, allocaArray )
-import Foreign.C.Types
-import Foreign.Ptr ( Ptr, castPtr )
-import Foreign.Storable ( Storable(..) )
-import Sound.OpenAL.AL.ALboolean ( unmarshalALboolean )
-import Sound.OpenAL.AL.BasicTypes ( ALboolean, ALuint, ALsizei )
-import Sound.OpenAL.AL.PeekPoke ( peek1, poke1 )
-
---------------------------------------------------------------------------------
-
--- | The abstract buffer type.
-
-newtype Buffer = Buffer { bufferID :: ALuint }
-   deriving ( Eq, Ord, Show )
- 
--- | A dummy buffer.
-
-nullBuffer :: Buffer
-nullBuffer = Buffer 0
-
-marshalBuffer :: Maybe Buffer -> ALuint
-marshalBuffer = bufferID . maybe nullBuffer id
-
-unmarshalBuffer :: ALuint -> Maybe Buffer
-unmarshalBuffer b =
-   if b == bufferID nullBuffer then Nothing else Just (Buffer b)
-
-instance Storable Buffer where
-   sizeOf    ~(Buffer b) = sizeOf b
-   alignment ~(Buffer b) = alignment b
-   peek                  = peek1 Buffer . castPtr
-   poke ptr   (Buffer b) = poke1 (castPtr ptr) b
-
---------------------------------------------------------------------------------
--- This should really be in Sound.OpenAL.AL.Buffer, but we have it here to
--- avoid an orphan module.
-
-instance ObjectName Buffer where
-   deleteObjectNames buffers =
-      withArrayLen buffers $ alDeleteBuffers . fromIntegral
-
-   isObjectName = fmap unmarshalALboolean . alIsBuffer
-
-instance GeneratableObjectName Buffer where
-   genObjectNames n =
-      allocaArray n $ \buf -> do
-        alGenBuffers (fromIntegral n) buf
-        peekArray n buf
-
-foreign import ccall unsafe "alGenBuffers"
-   alGenBuffers :: ALsizei -> Ptr Buffer -> IO ()
-
-foreign import ccall unsafe "alDeleteBuffers"
-   alDeleteBuffers :: ALsizei -> Ptr Buffer -> IO ()
-
-foreign import ccall unsafe "alIsBuffer"
-   alIsBuffer :: Buffer -> IO ALboolean
diff --git a/Sound/OpenAL/AL/Doppler.hs b/Sound/OpenAL/AL/Doppler.hs
deleted file mode 100644
--- a/Sound/OpenAL/AL/Doppler.hs
+++ /dev/null
@@ -1,92 +0,0 @@
-{-# LANGUAGE ForeignFunctionInterface #-}
-{-# OPTIONS_GHC -fno-warn-unused-imports #-}
---------------------------------------------------------------------------------
--- |
--- Module      :  Sound.OpenAL.AL.Doppler
--- Copyright   :  (c) Sven Panne 2003-2013
--- License     :  BSD3
--- 
--- Maintainer  :  Sven Panne <svenpanne@gmail.com>
--- Stability   :  stable
--- Portability :  portable
---
--- This module corresponds to section 3.5.2. (Velocity Dependent Doppler Effect)
--- of the OpenAL Specification and Reference (version 1.1).
--- 
---------------------------------------------------------------------------------
-
-module Sound.OpenAL.AL.Doppler (
-   -- * Introduction
-   -- $Introduction
-   dopplerFactor, speedOfSound
-) where
-
-import Foreign.C.Types
-import Foreign.Ptr
-import Graphics.Rendering.OpenGL.GL.StateVar
-import Sound.OpenAL.AL.BasicTypes
-import Sound.OpenAL.AL.Extensions
-import Sound.OpenAL.AL.QueryUtils
-
--- For Haddock only.
-import Sound.OpenAL.AL.Errors
-
---------------------------------------------------------------------------------
-
--- | 'dopplerFactor' is a simple scaling of source and listener velocities to
--- exaggerate or deemphasize the Doppler (pitch) shift resulting from the
--- calculation. Setting 'dopplerFactor' to a negative value will result in an
--- 'ALInvalidValue' error, the command is then ignored. The default value is 1.
--- The implementation is free to optimize the case of 'dopplerFactor' containing
--- zero, as this effectively disables the effect.
-
-dopplerFactor :: StateVar ALfloat
-dopplerFactor = makeDopplerVar GetDopplerFactor "alDopplerFactor"
-
---------------------------------------------------------------------------------
-
--- | 'speedOfSound' allows the application to change the reference (propagation)
--- speed used in the Doppler calculation. The source and listener velocities
--- should be expressed in the same units as the speed of sound. Setting
--- 'speedOfSound' to a negative or zero value will result in an 'ALInvalidValue'
--- error, the command is ignored then. The default value is 343.3 (appropriate
--- for velocity units of meters and air as the propagation medium).
-
-speedOfSound :: StateVar ALfloat
-speedOfSound = makeDopplerVar GetSpeedOfSound "alSpeedOfSound"
-
---------------------------------------------------------------------------------
-
-makeDopplerVar :: GetPName -> String -> StateVar ALfloat
-makeDopplerVar p apiEntryName =
-   makeStateVar
-      (alGetFloat (marshalGetPName p))
-      (\value -> do
-         -- ToDo: Should we check alcVersion or alIsExtensionPresent here?
-         funPtr <- get (alProcAddress apiEntryName)
-         invokeWithFloat funPtr value)
-
-foreign import ccall unsafe "alGetFloat"
-   alGetFloat :: ALenum -> IO ALfloat
-
-type Invoker a = FunPtr a -> a
-
-foreign import ccall unsafe "dynamic"
-   invokeWithFloat :: Invoker (ALfloat -> IO ()) 
-
---------------------------------------------------------------------------------
--- $Introduction
--- The Doppler Effect depends on the velocities of source and listener relative
--- to the medium, and the propagation speed of sound in that medium.  The
--- application might want to emphasize or de-emphasize the Doppler Effect as
--- physically accurate calculation might not give the desired results.
--- The amount of frequency shift (pitch change) is proportional to the speed of
--- listener and source along their line of sight.
--- 
--- The Doppler Effect as implemented by OpenAL is described in detail in section
--- 3.5.2 of the OpenAL 1.1 specification. Note that effects of the medium (air,
--- water) moving with respect to listener and source are ignored. There are two
--- API calls global to the current context that provide control of the Doppler
--- factor and the speed of sound. Distance and velocity units are completely
--- independent of one another (so you could use different units for each if
--- desired).
diff --git a/Sound/OpenAL/AL/Errors.hs b/Sound/OpenAL/AL/Errors.hs
deleted file mode 100644
--- a/Sound/OpenAL/AL/Errors.hs
+++ /dev/null
@@ -1,89 +0,0 @@
-{-# LANGUAGE ForeignFunctionInterface #-}
---------------------------------------------------------------------------------
--- |
--- Module      :  Sound.OpenAL.AL.Errors
--- Copyright   :  (c) Sven Panne 2003-2013
--- License     :  BSD3
--- 
--- Maintainer  :  Sven Panne <svenpanne@gmail.com>
--- Stability   :  stable
--- Portability :  portable
---
--- This module corresponds to section 2.7 (AL Errors) of the OpenAL
--- Specification and Reference (version 1.1).
---
---------------------------------------------------------------------------------
-
-module Sound.OpenAL.AL.Errors (
-   ALError(..), ALErrorCategory(..), alErrors
-) where
-
-import Foreign.C.Types
-import Graphics.Rendering.OpenGL.GL.StateVar
-import Sound.OpenAL.AL.BasicTypes ( ALenum )
-import Sound.OpenAL.Constants (
-   al_NO_ERROR, al_INVALID_NAME, al_INVALID_ENUM, al_INVALID_VALUE,
-   al_INVALID_OPERATION, al_OUT_OF_MEMORY )
-import Sound.OpenAL.AL.QueryUtils ( StringName(..), getString )
-
---------------------------------------------------------------------------------
-
--- | AL errors consist of a general error category and a description of what
--- went wrong.
-
-data ALError = ALError ALErrorCategory String
-   deriving ( Eq, Ord, Show )
-
---------------------------------------------------------------------------------
-
--- | General AL error categories.
-
-data ALErrorCategory =
-     ALInvalidEnum
-   | ALInvalidValue
-   | ALInvalidOperation
-   | ALInvalidName
-   | ALOutOfMemory
-   deriving ( Eq, Ord, Show )
-
-unmarshalALErrorCategory :: ALenum -> ALErrorCategory
-unmarshalALErrorCategory x
-   | x == al_INVALID_ENUM = ALInvalidEnum
-   | x == al_INVALID_VALUE = ALInvalidValue
-   | x == al_INVALID_OPERATION = ALInvalidOperation
-   | x == al_INVALID_NAME = ALInvalidName
-   | x == al_OUT_OF_MEMORY = ALOutOfMemory
-   | otherwise = error ("unmarshalALErrorCategory: illegal value " ++ show x)
-
---------------------------------------------------------------------------------
-
--- | OpenAL detects only a subset of those conditions that could be considered
--- errors. This is because in many cases error checking would adversely impact
--- the performance of an error-free program. The state variable 'alErrors' is
--- used to obtain error information. When an error is detected by AL, a flag is
--- set and the error code is recorded. Further errors, if they occur, do not
--- affect this recorded code. When 'alErrors' is read, the error is returned and
--- the flag is cleared, so that a further error will again record its code. If
--- reading 'alErrors' returns @\[\]@ then there has been no detectable error
--- since the last time 'alErrors' (or since the AL was initialized).
---
--- When an error flag is set, results of AL operations are undefined only if
--- 'ALOutOfMemory' has occurred. In other cases, the command generating the
--- error is ignored so that it has no effect on AL state or output buffer
--- contents. If the error generating command returns a value, it returns zero.
--- If the generating command modifies values through a pointer argument, no
--- change is made to these values. These error semantics apply only to AL
--- errors, not to system errors such as memory access errors.
-
-alErrors :: GettableStateVar [ALError]
-alErrors =
-   makeGettableStateVar $ do
-      c <- alGetError
-      if c == al_NO_ERROR
-         then return []
-         else do
-            s <- getString (ALErrorCategory c)
-            return [ ALError (unmarshalALErrorCategory c) s ]
-
-foreign import ccall unsafe "alGetError"
-   alGetError :: IO ALenum
diff --git a/Sound/OpenAL/AL/Extensions.hs b/Sound/OpenAL/AL/Extensions.hs
deleted file mode 100644
--- a/Sound/OpenAL/AL/Extensions.hs
+++ /dev/null
@@ -1,105 +0,0 @@
-{-# LANGUAGE ForeignFunctionInterface #-}
---------------------------------------------------------------------------------
--- |
--- Module      :  Sound.OpenAL.AL.Extensions
--- Copyright   :  (c) Sven Panne 2003-2013
--- License     :  BSD3
--- 
--- Maintainer  :  Sven Panne <svenpanne@gmail.com>
--- Stability   :  stable
--- Portability :  portable
---
--- This module corresponds to section 3.1.2 (String Queries) and chapter 7
--- (Appendix: Extensions) of the OpenAL Specification and Reference (version
--- 1.1).
---
---------------------------------------------------------------------------------
-
-module Sound.OpenAL.AL.Extensions (
-   -- * General AL extension support
-   alExtensions, alIsExtensionPresent, alProcAddress, alEnumValue, alVersion,
-
-   -- * Internal re-exports, use at your own risk
-   unmarshalALboolean, unmarshalFormat, unmarshalBuffer
-) where
-
-import Foreign.C.Types
-import Foreign.Ptr
-import Graphics.Rendering.OpenGL.GL.StateVar
-import Sound.OpenAL.AL.ALboolean
-import Sound.OpenAL.AL.BasicTypes
-import Sound.OpenAL.AL.BufferInternal
-import Sound.OpenAL.AL.Format
-import Sound.OpenAL.AL.QueryUtils
-import Sound.OpenAL.AL.String
-
---------------------------------------------------------------------------------
-
--- | Contains the list of available extensions.
-
-alExtensions :: GettableStateVar [String]
-alExtensions = makeGettableStateVar (fmap words $ getString Extensions)
-
---------------------------------------------------------------------------------
-
--- | Contains a version string in the format @\"/\<spec major number\>/./\<spec
--- minor number\>/ /\<optional vendor version information\>/\"@.
-
-alVersion :: GettableStateVar String
-alVersion = makeGettableStateVar (getString Version)
-
---------------------------------------------------------------------------------
-
--- | To verify that a given extension is available for the current context, use
--- 'alIsExtensionPresent'. For invalid and unsupported string tokens it contains
--- 'False'. The extension name is not case sensitive: The implementation will
--- convert the name to all upper-case internally (and will express extension
--- names in upper-case).
-
-alIsExtensionPresent :: String -> GettableStateVar Bool
-alIsExtensionPresent extensionName =
-   makeGettableStateVar $
-      fmap unmarshalALboolean $
-         withALString extensionName alIsExtensionPresent_
-
-foreign import ccall unsafe "alIsExtensionPresent"
-   alIsExtensionPresent_ :: Ptr ALchar -> IO ALboolean
-
---------------------------------------------------------------------------------
-
--- | To retrieving function entry addresses, applications can use
--- 'alProcAddress'. It contains 'nullFunPtr' if no entry point with the given
--- name can be found. Implementations are free to use 'nullFunPtr' if an
--- entry point is present, but not applicable for the current context. However
--- the specification does not guarantee this behavior. Applications can use
--- 'alProcAddress' to obtain core API entry points, not just extensions. This
--- is the recommended way to dynamically load and unload OpenAL DLLs as sound
--- drivers.
-
-alProcAddress :: String -> GettableStateVar (FunPtr a)
-alProcAddress funcName = makeGettableStateVar $
-   withALString funcName alGetProcAddress
-
-foreign import ccall unsafe "alGetProcAddress"
-   alGetProcAddress :: Ptr ALchar -> IO (FunPtr a)
-
---------------------------------------------------------------------------------
-
--- | To obtain enumeration values for extensions, the application has to use
--- 'alEnumValue' of an extension token. Enumeration values are defined within
--- the OpenAL name space and allocated according to specification of the core
--- API and the extensions, thus they are context-independent.
---
--- 'alEnumValue' contains 0 if the enumeration can not be found. The presence of
--- an enum value does not guarantee the applicability of an extension to the
--- current context. A non-zero value indicates merely that the implementation is
--- aware of the existence of this extension. Implementations should not attempt
--- to use 0 to indicate that the extensions is not supported for the current
--- context.
-
-alEnumValue :: String -> GettableStateVar ALenum
-alEnumValue enumName = makeGettableStateVar $
-   withALString enumName alGetEnumValue
-
-foreign import ccall unsafe "alGetEnumValue"
-   alGetEnumValue :: Ptr ALchar -> IO ALenum
diff --git a/Sound/OpenAL/AL/Format.hs b/Sound/OpenAL/AL/Format.hs
deleted file mode 100644
--- a/Sound/OpenAL/AL/Format.hs
+++ /dev/null
@@ -1,50 +0,0 @@
-{-# OPTIONS_HADDOCK hide #-}
---------------------------------------------------------------------------------
--- |
--- Module      :  Sound.OpenAL.AL.Format
--- Copyright   :  (c) Sven Panne 2003-2013
--- License     :  BSD3
--- 
--- Maintainer  :  Sven Panne <svenpanne@gmail.com>
--- Stability   :  stable
--- Portability :  portable
---
--- This is a purely internal module for (un-)marshaling Format.
---
---------------------------------------------------------------------------------
-
-module Sound.OpenAL.AL.Format (
-   Format(..), marshalFormat, unmarshalFormat
-) where
-
-import Sound.OpenAL.AL.BasicTypes ( ALenum )
-import Sound.OpenAL.Constants (
-   al_FORMAT_MONO8, al_FORMAT_MONO16, al_FORMAT_STEREO8, al_FORMAT_STEREO16 )
-
---------------------------------------------------------------------------------
-
--- | Valid sound formats. An implementation may expose other formats, see
--- "Sound.OpenAL.ALC.Extensions" for information on determining if additional
--- formats are supported.
-
-data Format =
-     Mono8
-   | Mono16
-   | Stereo8
-   | Stereo16
-   deriving ( Eq, Ord, Show )
-
-marshalFormat :: Format -> ALenum
-marshalFormat x = case x of
-   Mono8 -> al_FORMAT_MONO8
-   Mono16 -> al_FORMAT_MONO16
-   Stereo8 -> al_FORMAT_STEREO8
-   Stereo16 -> al_FORMAT_STEREO16
-
-unmarshalFormat :: ALenum -> Format
-unmarshalFormat x
-   | x == al_FORMAT_MONO8 = Mono8
-   | x == al_FORMAT_MONO16 = Mono16
-   | x == al_FORMAT_STEREO8 = Stereo8
-   | x == al_FORMAT_STEREO16 = Stereo16
-   | otherwise = error ("unmarshalFormat: illegal value " ++ show x)
diff --git a/Sound/OpenAL/AL/Listener.hs b/Sound/OpenAL/AL/Listener.hs
deleted file mode 100644
--- a/Sound/OpenAL/AL/Listener.hs
+++ /dev/null
@@ -1,150 +0,0 @@
-{-# LANGUAGE ForeignFunctionInterface #-}
---------------------------------------------------------------------------------
--- |
--- Module      :  Sound.OpenAL.AL.Listener
--- Copyright   :  (c) Sven Panne 2003-2013
--- License     :  BSD3
--- 
--- Maintainer  :  Sven Panne <svenpanne@gmail.com>
--- Stability   :  stable
--- Portability :  portable
---
--- This module corresponds to sections 4.1 (Basic Listener and Source
--- Attributes) and 4.2 (Listener Object) of the OpenAL Specification and
--- Reference (version 1.1).
--- 
--- The listener object defines various properties that affect processing of the
--- sound for the actual output. The listener is unique for an OpenAL Context,
--- and has no name. By controlling the listener, the application controls the
--- way the user experiences the virtual world, as the listener defines the
--- sampling\/pickup point and orientation, and other parameters that affect the
--- output stream.
--- 
--- It is entirely up to the driver and hardware configuration, i.e. the
--- installation of OpenAL as part of the operating system and hardware setup,
--- whether the output stream is generated for headphones or 2 speakers, 4.1
--- speakers, or other arrangements, whether (and which) HRTFs are applied,
--- etc...
---
----------------------------------------------------------------------------------
-
-module Sound.OpenAL.AL.Listener (
-   listenerPosition, listenerVelocity, Gain, listenerGain, orientation
-) where
-
-import Graphics.Rendering.OpenGL.GL.StateVar
-import Graphics.Rendering.OpenGL.GL.Tensor
-import Foreign.C.Types
-import Foreign.Marshal.Array
-import Foreign.Marshal.Utils
-import Foreign.Ptr
-import Foreign.Storable
-import Sound.OpenAL.AL.BasicTypes
-import Sound.OpenAL.AL.PeekPoke
-import Sound.OpenAL.AL.QueryUtils
-
---------------------------------------------------------------------------------
-
--- | 'listenerPosition' contains the current location of the listener in the
--- world coordinate system. Any 3-tuple of valid float values is allowed.
--- Implementation behavior on encountering NaN and infinity is not defined. The
--- initial position is ('Vertex3' 0 0 0).
-
-listenerPosition :: StateVar (Vertex3 ALfloat)
-listenerPosition = makeListenerVar GetPosition 3 (peek3 Vertex3) listener3f
-
---------------------------------------------------------------------------------
-
--- | 'listenerVelocity' contains current velocity (speed and direction) of the
--- listener in the world coordinate system. Any 3-tuple of valid float
--- values is allowed, and the initial velocity is ('Vector3' 0 0 0).
--- 'listenerVelocity' does not affect 'listenerPosition'. OpenAL does not
--- calculate the velocity from subsequent position updates, nor does it
--- adjust the position over time based on the specified velocity. Any
--- such calculation is left to the application. For the purposes of sound
--- processing, position and velocity are independent parameters affecting
--- different aspects of the sounds.
---
--- 'listenerVelocity' is taken into account by the driver to synthesize the
--- Doppler effect perceived by the listener for each source, based on the
--- velocity of both source and listener, and the Doppler related parameters.
-
-listenerVelocity :: StateVar (Vector3 ALfloat)
-listenerVelocity = makeListenerVar GetVelocity 3 (peek3 Vector3) listener3f
-
---------------------------------------------------------------------------------
-
--- | A scalar amplitude multiplier.
-type Gain = ALfloat
-
--- | 'listenerGain' contains a scalar amplitude multiplier, which is effectively
--- applied to all sources in the current context. The initial value 1 means
--- that the sound is unattenuated. A 'listenerGain' value of 0.5 is equivalent
--- to an attenuation of 6dB. The value zero equals silence (no output). Driver
--- implementations are free to optimize this case and skip mixing and processing
--- stages where applicable. The implementation is in charge of ensuring
--- artifact-free (click-free) changes of gain values and is free to defer actual
--- modification of the sound samples, within the limits of acceptable latencies.
---
--- A 'listenerGain' larger than 1 (amplification) is permitted. However, the
--- implementation is free to clamp the total gain (effective gain per source
--- times listener gain) to 1 to prevent overflow.
-
-listenerGain :: StateVar Gain
-listenerGain = makeListenerVar GetGain 1 (peek1 id) listenerf
-
---------------------------------------------------------------------------------
-
--- | 'orientation' contains an \"at\" vector and an \"up\" vector, where the
--- \"at\" vector represents the \"forward\" direction of the listener and the
--- orthogonal projection of the \"up\" vector into the subspace perpendicular to
--- the \"at\" vector represents the \"up\" direction for the listener. OpenAL
--- expects two vectors that are linearly independent. These vectors are not
--- expected to be normalized. If the two vectors are linearly dependent,
--- behavior is undefined. The initial orientation is ('Vector3' 0 0 (-1),
--- 'Vector3' 0 1 0), i.e. looking down the Z axis with the Y axis pointing
--- upwards.
-
-orientation :: StateVar (Vector3 ALfloat, Vector3 ALfloat)
-orientation = makeListenerVar GetOrientation 6 (peek6 Vector3) listenerVector6
-
---------------------------------------------------------------------------------
-
-listenerf :: GetPName -> ALfloat -> IO ()
-listenerf = alListenerf . marshalGetPName
-
-foreign import ccall unsafe "alListenerf"
-   alListenerf :: ALenum -> ALfloat -> IO ()
-
---------------------------------------------------------------------------------
-
-listener3f :: Storable a => GetPName -> a -> IO ()
-listener3f n x = with x $ listenerfv n
-
-listenerVector6 :: GetPName -> (Vector3 ALfloat, Vector3 ALfloat) -> IO ()
-listenerVector6 n (x, y) = withArray [x, y] $ listenerfv n
-
-listenerfv :: GetPName -> Ptr a -> IO ()
-listenerfv = alListenerfv . marshalGetPName
-
-foreign import ccall unsafe "alListenerfv"
-   alListenerfv :: ALenum -> Ptr a -> IO ()
-
---------------------------------------------------------------------------------
-
-getListenerfv :: GetPName -> Ptr ALfloat -> IO ()
-getListenerfv = alGetListenerfv . marshalGetPName
-
-foreign import ccall unsafe "alGetListenerfv"
-   alGetListenerfv :: ALenum -> Ptr ALfloat -> IO ()
-
---------------------------------------------------------------------------------
-
-makeListenerVar :: GetPName -> Int -> (Ptr ALfloat -> IO a)
-                -> (GetPName -> a -> IO ()) -> StateVar a
-makeListenerVar pname size reader writer =
-   makeStateVar
-      (allocaArray size $ \buf -> do
-          getListenerfv pname buf
-          reader buf)
-      (writer pname)
diff --git a/Sound/OpenAL/AL/PeekPoke.hs b/Sound/OpenAL/AL/PeekPoke.hs
deleted file mode 100644
--- a/Sound/OpenAL/AL/PeekPoke.hs
+++ /dev/null
@@ -1,59 +0,0 @@
-{-# OPTIONS_HADDOCK hide #-}
---------------------------------------------------------------------------------
--- |
--- Module      :  Sound.OpenAL.AL.PeekPoke
--- Copyright   :  (c) Sven Panne 2003-2013
--- License     :  BSD3
--- 
--- Maintainer  :  Sven Panne <svenpanne@gmail.com>
--- Stability   :  stable
--- Portability :  portable
---
--- This is a purely internal module with peek- and poke-related utilities.
---
---------------------------------------------------------------------------------
-
-module Sound.OpenAL.AL.PeekPoke (
-   poke1, peek1, peek3, peek6
-) where
-
-import Foreign.Ptr ( Ptr )
-import Foreign.Storable ( Storable(peekElemOff,pokeElemOff) )
-
---------------------------------------------------------------------------------
--- The implementation is little bit verbose/redundant, but seems to generate
--- better code than mapM/zipWithM_.
-
---------------------------------------------------------------------------------
-
-{-# INLINE poke1 #-}
-poke1 :: Storable a => Ptr a -> a -> IO ()
-poke1 ptr x =
-   pokeElemOff ptr 0 x
-
---------------------------------------------------------------------------------
-
-{-# INLINE peek1 #-}
-peek1 :: Storable a => (a -> b) -> Ptr a -> IO b
-peek1 f ptr = do
-   x <- peekElemOff ptr 0
-   return $ f x
-
-{-# INLINE peek3 #-}
-peek3 :: Storable a => (a -> a -> a -> b) -> Ptr a -> IO b
-peek3 f ptr = do
-   x <- peekElemOff ptr 0
-   y <- peekElemOff ptr 1
-   z <- peekElemOff ptr 2
-   return $ f x y z
-
-{-# INLINE peek6 #-}
-peek6 :: Storable a => (a -> a -> a -> b) -> Ptr a -> IO (b, b)
-peek6 f ptr = do
-   x <- peekElemOff ptr 0
-   y <- peekElemOff ptr 1
-   z <- peekElemOff ptr 2
-   u <- peekElemOff ptr 3
-   v <- peekElemOff ptr 4
-   w <- peekElemOff ptr 5
-   return $ (f x y z, f u v w)
diff --git a/Sound/OpenAL/AL/QueryUtils.hs b/Sound/OpenAL/AL/QueryUtils.hs
deleted file mode 100644
--- a/Sound/OpenAL/AL/QueryUtils.hs
+++ /dev/null
@@ -1,124 +0,0 @@
-{-# LANGUAGE ForeignFunctionInterface #-}
-{-# OPTIONS_HADDOCK hide #-}
---------------------------------------------------------------------------------
--- |
--- Module      :  Sound.OpenAL.AL.QueryUtils
--- Copyright   :  (c) Sven Panne 2003-2013
--- License     :  BSD3
--- 
--- Maintainer  :  Sven Panne <svenpanne@gmail.com>
--- Stability   :  stable
--- Portability :  portable
---
--- This is a purely internal module with utilities to query OpenAL state.
---
---------------------------------------------------------------------------------
-
-module Sound.OpenAL.AL.QueryUtils (
-   GetPName(..), marshalGetPName,
-   StringName(..), getString
-) where
-
-import Foreign.C.Types
-import Foreign.Ptr ( Ptr )
-import Sound.OpenAL.AL.BasicTypes ( ALchar, ALenum )
-import Sound.OpenAL.AL.String ( peekALString )
-import Sound.OpenAL.Constants (
-   al_DISTANCE_MODEL, al_DOPPLER_FACTOR, al_SPEED_OF_SOUND, al_POSITION,
-   al_VELOCITY, al_GAIN, al_ORIENTATION, al_SOURCE_RELATIVE, al_SOURCE_TYPE,
-   al_LOOPING, al_BUFFER, al_BUFFERS_QUEUED, al_BUFFERS_PROCESSED, al_MIN_GAIN,
-   al_MAX_GAIN, al_REFERENCE_DISTANCE, al_ROLLOFF_FACTOR, al_MAX_DISTANCE,
-   al_PITCH, al_DIRECTION, al_CONE_INNER_ANGLE, al_CONE_OUTER_ANGLE,
-   al_CONE_OUTER_GAIN, al_SEC_OFFSET, al_SAMPLE_OFFSET, al_BYTE_OFFSET,
-   al_SOURCE_STATE, al_VENDOR, al_RENDERER, al_VERSION, al_EXTENSIONS )
-
---------------------------------------------------------------------------------
-
-data GetPName =
-     GetDistanceModel
-   | GetDopplerFactor
-   | GetSpeedOfSound
-
-   | GetPosition
-
-   | GetVelocity
-   | GetGain
-
-   | GetOrientation
-
-   | GetSourceRelative
-   | GetSourceType
-   | GetLooping
-   | GetBuffer
-   | GetBuffersQueued
-   | GetBuffersProcessed
-   | GetMinGain
-   | GetMaxGain
-   | GetReferenceDistance
-   | GetRolloffFactor
-   | GetMaxDistance
-   | GetPitch
-   | GetDirection
-   | GetConeInnerAngle
-   | GetConeOuterAngle
-   | GetConeOuterGain
-   | GetSecOffset
-   | GetSampleOffset
-   | GetByteOffset
-   | GetSourceState
-
-marshalGetPName :: GetPName -> ALenum
-marshalGetPName x = case x of
-   GetDistanceModel -> al_DISTANCE_MODEL
-   GetDopplerFactor -> al_DOPPLER_FACTOR
-   GetSpeedOfSound -> al_SPEED_OF_SOUND
-
-   GetPosition -> al_POSITION
-   GetVelocity -> al_VELOCITY
-   GetGain -> al_GAIN
-
-   GetOrientation -> al_ORIENTATION
-
-   GetSourceRelative -> al_SOURCE_RELATIVE
-   GetSourceType -> al_SOURCE_TYPE
-   GetLooping -> al_LOOPING
-   GetBuffer -> al_BUFFER
-   GetBuffersQueued -> al_BUFFERS_QUEUED
-   GetBuffersProcessed -> al_BUFFERS_PROCESSED
-   GetMinGain -> al_MIN_GAIN
-   GetMaxGain -> al_MAX_GAIN
-   GetReferenceDistance -> al_REFERENCE_DISTANCE
-   GetRolloffFactor -> al_ROLLOFF_FACTOR
-   GetMaxDistance -> al_MAX_DISTANCE
-   GetPitch -> al_PITCH
-   GetDirection -> al_DIRECTION
-   GetConeInnerAngle -> al_CONE_INNER_ANGLE
-   GetConeOuterAngle -> al_CONE_OUTER_ANGLE
-   GetConeOuterGain -> al_CONE_OUTER_GAIN
-   GetSecOffset -> al_SEC_OFFSET
-   GetSampleOffset -> al_SAMPLE_OFFSET
-   GetByteOffset -> al_BYTE_OFFSET
-   GetSourceState -> al_SOURCE_STATE
-
---------------------------------------------------------------------------------
-
-data StringName =
-     Vendor
-   | Renderer
-   | Version
-   | Extensions
-   | ALErrorCategory ALenum
-
-marshalStringName :: StringName -> ALenum
-marshalStringName x = case x of
-   Vendor -> al_VENDOR
-   Renderer -> al_RENDERER
-   Version -> al_VERSION
-   Extensions -> al_EXTENSIONS
-   ALErrorCategory e -> e
-
-getString :: StringName -> IO String
-getString n = alGetString (marshalStringName n) >>= peekALString 
-
-foreign import ccall unsafe "alGetString"
-   alGetString :: ALenum -> IO (Ptr ALchar)
diff --git a/Sound/OpenAL/AL/Source.hs b/Sound/OpenAL/AL/Source.hs
deleted file mode 100644
--- a/Sound/OpenAL/AL/Source.hs
+++ /dev/null
@@ -1,768 +0,0 @@
-{-# LANGUAGE ForeignFunctionInterface #-}
-{-# OPTIONS_GHC -fno-warn-unused-imports #-}
---------------------------------------------------------------------------------
--- |
--- Module      :  Sound.OpenAL.AL.Source
--- Copyright   :  (c) Sven Panne 2003-2013
--- License     :  BSD3
--- 
--- Maintainer  :  Sven Panne <svenpanne@gmail.com>
--- Stability   :  stable
--- Portability :  portable
---
--- This module corresponds to sections 4.1 (Basic Listener and Source
--- Attributes) and 4.3 (Source Objects) of the OpenAL Specification and
--- Reference (version 1.1).
---
--- Sources specify attributes like position, velocity, and a buffer with sample
--- data. By controlling a source\'s attributes the application can modify and
--- parameterize the static sample data provided by the buffer referenced by the
--- source. Sources define a localized sound, and encapsulate a set of attributes
--- applied to a sound at its origin, i.e. in the very first stage of the
--- processing on the way to the listener. Source related effects have to be
--- applied before listener related effects unless the output is invariant to any
--- collapse or reversal of order. OpenAL also provides additional functions to
--- manipulate and query the execution state of sources: the current playing
--- status of a source, including access to the current sampling position within
--- the associated buffer.
---
---------------------------------------------------------------------------------
-
-module Sound.OpenAL.AL.Source (
-   -- * The Source Type
-   Source,
-
-   -- * Source Attributes
-
-   -- ** Basic Source Attributes
-   sourcePosition, sourceVelocity, sourceGain,
-
-   -- ** Source Positioning
-   SourceRelative(..), sourceRelative,
-
-   -- ** Source Type
-   SourceType(..), sourceType,
-
-   -- ** Buffer Looping
-   LoopingMode(..), loopingMode,
-
-   -- ** Current Buffer
-   buffer,
-
-   -- ** Queue State Queries
-   buffersQueued, buffersProcessed,
-
-   -- ** Bounds on Gain
-   gainBounds,
-
-   -- ** Distance Model Attributes
-   referenceDistance, rolloffFactor, maxDistance,
-
-   -- ** Frequency Shift by Pitch
-   pitch,
-
-   -- ** Direction and Cone
-   -- $DirectionAndCone
-   direction, coneAngles, coneOuterGain,
-
-   -- ** Offset
-   secOffset, sampleOffset, byteOffset,
-
-   -- * Queuing Buffers with a Source
-   -- $QueuingBuffersWithASource
-   queueBuffers, unqueueBuffers,
-
-   -- * Managing Source Execution
-   -- $ManagingSourceExecution
-   SourceState(..), sourceState, play, pause, stop, rewind
-) where
-
-import Control.Monad
-import Foreign.C.Types
-import Foreign.Marshal.Array
-import Foreign.Marshal.Utils
-import Foreign.Ptr
-import Foreign.Storable
-import Graphics.Rendering.OpenGL.GL.ObjectName
-import Graphics.Rendering.OpenGL.GL.StateVar
-import Graphics.Rendering.OpenGL.GL.Tensor
-import Sound.OpenAL.AL.ALboolean
-import Sound.OpenAL.AL.BasicTypes
-import Sound.OpenAL.AL.BufferInternal
-import Sound.OpenAL.AL.Listener
-import Sound.OpenAL.AL.PeekPoke
-import Sound.OpenAL.AL.QueryUtils
-import Sound.OpenAL.AL.SourceState
-import Sound.OpenAL.Constants
-
--- For Haddock only.
-import Sound.OpenAL.AL.Errors
-
---------------------------------------------------------------------------------
-
--- | The abstract buffer type.
-
-newtype Source = Source ALuint
-   deriving ( Eq, Ord, Show )
-
-instance Storable Source where
-   sizeOf    ~(Source b) = sizeOf b
-   alignment ~(Source b) = alignment b
-   peek                  = peek1 Source . castPtr
-   poke ptr   (Source b) = poke1 (castPtr ptr) b
-
-instance ObjectName Source where
-   deleteObjectNames = withArraySizei alDeleteSources
-
-   isObjectName = fmap unmarshalALboolean . alIsSource
-
-instance GeneratableObjectName Source where
-   genObjectNames n =
-      allocaArray n $ \buf -> do
-         alGenSources (fromIntegral n) buf
-         peekArray n buf
-
-foreign import ccall unsafe "alGenSources"
-   alGenSources :: ALsizei -> Ptr Source -> IO ()
-
-foreign import ccall unsafe "alDeleteSources"
-   alDeleteSources :: ALsizei -> Ptr Source -> IO ()
-
-foreign import ccall unsafe "alIsSource"
-   alIsSource :: Source -> IO ALboolean
-
---------------------------------------------------------------------------------
-
--- | 'sourcePosition' contains the current location of the source in the world
--- coordinate system. Any 3-tuple of valid float values is allowed.
--- Implementation behavior on encountering NaN and infinity is not defined. The
--- initial position is ('Vertex3' 0 0 0).
-
-sourcePosition :: Source -> StateVar (Vertex3 ALfloat)
-sourcePosition = makeSourceStateVar dictVertex3ALfloat GetPosition
-
--- | 'sourceVelocity' contains current velocity (speed and direction) of the
--- source in the world coordinate system. Any 3-tuple of valid float values is
--- allowed, and the initial velocity is ('Vector3' 0 0 0). 'sourceVelocity' does
--- not affect 'sourcePosition'. OpenAL does not calculate the velocity from
--- subsequent position updates, nor does it adjust the position over time based
--- on the specified velocity. Any such calculation is left to the application.
--- For the purposes of sound processing, position and velocity are independent
--- parameters affecting different aspects of the sounds.
---
--- 'sourceVelocity' is taken into account by the driver to synthesize the
--- Doppler effect perceived by the listener for each source, based on the
--- velocity of both source and listener, and the Doppler related parameters.
-
-sourceVelocity :: Source -> StateVar (Vector3 ALfloat)
-sourceVelocity = makeSourceStateVar dictVector3ALfloat GetVelocity
-
--- | 'sourceGain' contains a scalar amplitude multiplier for the given source.
--- The initial value 1 means that the sound is unattenuated. A 'sourceGain'
--- value of 0.5 is equivalent to an attenuation of 6dB. The value zero equals
--- silence (no output). Driver implementations are free to optimize this case
--- and skip mixing and processing stages where applicable. The implementation is
--- in charge of ensuring artifact-free (click-free) changes of gain values and
--- is free to defer actual modification of the sound samples, within the limits
--- of acceptable latencies.
---
--- A 'sourceGain' larger than 1 (amplification) is permitted. However, the
--- implementation is free to clamp the total gain (effective gain per source
--- times listener gain) to 1 to prevent overflow.
-
-sourceGain :: Source -> StateVar Gain
-sourceGain = makeSourceStateVar dictALfloat GetGain
-
---------------------------------------------------------------------------------
-
--- | The entity to which the source attributes 'sourcePosition',
--- 'sourceVelocity' and 'direction' are to be interpreted.
-
-data SourceRelative =
-     World
-   | Listener
-   deriving ( Eq, Ord, Show )
-
-marshalSourceRelative :: SourceRelative -> Bool
-marshalSourceRelative = (== Listener)
-
-unmarshalSourceRelative :: Bool -> SourceRelative
-unmarshalSourceRelative x = if x then Listener else World
-
--- | If 'sourceRelative' contains 'Listener', it indicates indicates that the
--- values specified by 'sourcePosition', 'sourceVelocity' and 'direction' are to
--- be interpreted relative to the listener position. The initial value is
--- 'World', indicating that those source attributes are to be interpreted
--- relative to the world, i.e. they are considered absolute.
-
-sourceRelative :: Source -> StateVar SourceRelative
-sourceRelative = makeSourceStateVar dictSourceRelative GetSourceRelative
-
---------------------------------------------------------------------------------
-
--- | When first created, a source will be in the 'Undetermined' state. If a
--- buffer is then attached using 'buffer', then the source will enter the
--- 'Static' state. If the first buffer attached to a source is attached using
--- 'queueBuffers', then the source will enter the 'Streaming' state. A source of
--- either state will be reset to state 'Undetermined' by setting its 'buffer' to
--- 'Nothing', and attaching any buffer to a streaming source will change the
--- state to 'Static'. Attempting to queue a buffer on a static source will
--- result in an 'ALInvalidOperation' error.
-
-data SourceType =
-     Undetermined
-   | Static
-   | Streaming
-   deriving ( Eq, Ord, Show )
-
-unmarshalSourceType :: ALint -> SourceType
-unmarshalSourceType x
-   | x == al_UNDETERMINED = Undetermined
-   | x == al_STATIC = Static
-   | x == al_STREAMING = Streaming
-   | otherwise = error ("unmarshalSourceType: illegal value " ++ show x)
-
--- | 'sourceType' indicates whether a source is ready to queue buffers, ready to
--- use a static buffer, or is in an undetermined state where it can be used for
--- either streaming or static playback.
-
-sourceType :: Source -> GettableStateVar SourceType
-sourceType = makeSourceGettableStateVar dictSourceType GetSourceType
-
---------------------------------------------------------------------------------
-
--- | Specifies what should happen when the end of a buffer queue is reached.
-
-data LoopingMode =
-     OneShot
-   | Looping
-   deriving ( Eq, Ord, Show )
-
-marshalLoopingMode :: LoopingMode -> Bool
-marshalLoopingMode = (== Looping)
-
-unmarshalLoopingMode :: Bool -> LoopingMode
-unmarshalLoopingMode x = if x then Looping else OneShot
-
--- | If 'loopingMode' contains 'Looping', it indicates that the source will not
--- be in the 'Stopped' state once it reaches the end of last buffer in the
--- buffer queue. Instead, the source will immediately promote to 'Initial' and
--- 'Playing'.  The initial value is 'OneShot'. 'loopingMode' can be changed on a
--- source in any execution state. In particular, it can be changed on a
--- 'Playing' source.
-
-loopingMode :: Source -> StateVar LoopingMode
-loopingMode = makeSourceStateVar dictLoopingMode GetLooping
-
---------------------------------------------------------------------------------
-
--- | 'buffer' contains the current buffer object. Setting 'buffer' to 'Just' a
--- buffer object makes it the head entry in the source\'s queue. Setting
--- 'buffer'for a source in the 'Stopped' or 'Initial' state empties the entire
--- queue, then appends the one buffer specified (or none at all if 'Nothing'
--- was specified).
--- 
--- For a source in the 'Playing' or 'Paused' state, setting 'buffer' will result
--- in the 'ALInvalidOperation' error state being set. 'buffer' can be applied only
--- to sources in the 'Initial' and 'Stopped' states. Specifying an invalid
--- buffer name (either because the buffer name doesn\'t exist or because that
--- buffer can\'t be attached to the specified source) will result in an
--- 'ALInvalidValue' error while specifying an invalid source name results in an
--- 'ALInvalidName' error. Setting 'buffer' to 'Nothing' is a legal way to release
--- the current buffer queue on a source in the 'Initial' or 'Stopped' state,
--- whether the source has just one entry (current buffer) or more. Setting
--- 'buffer' to 'Nothing' still causes an 'ALInvalidOperation' for any source in
--- the 'Playing' or 'Paused' state, consequently it cannot be used to mute or
--- stop a source. The initial value is 'Nothing'.
-
-buffer :: Source -> StateVar (Maybe Buffer)
-buffer = makeSourceStateVar dictMaybeBuffer GetBuffer
-
---------------------------------------------------------------------------------
-
--- | 'buffersQueued' contains the number of buffers in the queue of a given
--- source. This includes those not yet played, the one currently playing, and
--- the ones that have been played already. It will contain 0 if 'buffer' has
--- been set to 'Nothing'.
-
-buffersQueued :: Source -> GettableStateVar ALint
-buffersQueued = makeSourceGettableStateVar dictALint GetBuffersQueued
-
--- | 'buffersProcessed' contains the number of buffers that have been played
--- by a given source.  Indirectly, this gives the index of the buffer currently
--- playing. It can be used to determine how much slots are needed for unqueuing
--- them. On a source in the 'Stopped' state, all buffers are processed. On a
--- source in the 'Initial' state, no buffers are processed, all buffers are
--- pending. It will contain 0 if 'buffer' has been set to 'Nothing'.
-
-buffersProcessed :: Source -> GettableStateVar ALint
-buffersProcessed = makeSourceGettableStateVar dictALint GetBuffersProcessed
-
---------------------------------------------------------------------------------
-
--- | 'gainBounds' contains two scalar amplitude thresholds between 0 and 1
--- (included): The minimum guaranteed gain for this source and the maximum gain
--- permitted, with initial values 0 and 1, respectively At the end of the
--- processing of various attenuation factors such as distance based attenuation
--- and 'sourceGain', the effective gain calculated is compared to these values:
---
--- If the effective gain is lower than the minimum gain, the minimum gain is
--- applied. This happens before the 'listenerGain' is applied. If a zero minimum
--- gain is set, then the effective gain will not be corrected.
---
--- If the effective gain is higher than the maximum gain, the maximum gain is
--- applied. This happens before the 'listenerGain' is applied. If the
--- 'listenerGain' times the maximum gain still exceeds the maximum gain the
--- implementation can handle, the implementation is free to clamp. If a zero
--- maximum gain is set, then the source is effectively muted. The implementation
--- is free to optimize for this situation, but no optimization is required or
--- recommended as setting 'sourceGain' to zero is the proper way to mute a
--- source.
-
-gainBounds :: Source -> StateVar (Gain, Gain)
-gainBounds source =
-   pairStateVars
-      (makeSourceStateVar dictALfloat GetMinGain source)
-      (makeSourceStateVar dictALfloat GetMaxGain source)
-
---------------------------------------------------------------------------------
-
--- | 'referenceDistance' is used for distance attenuation calculations based on
--- inverse distance with rolloff. Depending on the distance model it will also
--- act as a distance threshold below which gain is clamped. See
--- "Sound.OpenAL.AL.Attenuation" for details. The initial value is 1.
-
-referenceDistance :: Source -> StateVar ALfloat
-referenceDistance = makeSourceStateVar dictALfloat GetReferenceDistance
-
--- | 'rolloffFactor' is used for distance attenuation calculations based on
--- inverse distance with rolloff. For distances smaller than 'maxDistance' (and,
--- depending on the distance model, larger than 'referenceDistance'), this will
--- scale the distance attenuation over the applicable range. See
--- "Sound.OpenAL.AL.Attenuation" for details how the attenuation is computed as
--- a function of the distance. The initial value is 1.
--- 
--- In particular, 'rolloffFactor' can be set to zero for those sources that are
--- supposed to be exempt from distance attenuation. The implementation is
--- encouraged to optimize this case, bypassing distance attenuation calculation
--- entirely on a persource basis.
-
-rolloffFactor :: Source -> StateVar ALfloat
-rolloffFactor = makeSourceStateVar dictALfloat GetRolloffFactor
-
--- | 'maxDistance' is used for distance attenuation calculations based on
--- inverse distance with rolloff, if the inverse clamped distance model is
--- used. In this case, distances greater than 'maxDistance' will be clamped to
--- 'maxDistance'.  'maxDistance' based clamping is applied before minimum gain
--- clamping (see 'gainBounds'), so if the effective gain at 'maxDistance' is
--- larger than the minimum gain, the minimum gain will have no effect. No
--- culling is supported. The initial value is the largest representable
--- 'ALfloat'.
-
-maxDistance :: Source -> StateVar ALfloat
-maxDistance = makeSourceStateVar dictALfloat GetMaxDistance
-
---------------------------------------------------------------------------------
-
--- | 'pitch' contains the desired pitch shift, where 1 (the initial value)
--- equals identity. Each reduction by 50 percent equals a pitch shift of -12
--- semitones (one octave reduction). Each doubling equals a pitch shift of 12
--- semitones (one octave increase). Zero is not a legal value. Implementations
--- may clamp the actual output pitch range to any values subject to the
--- implementation's own limits.
-
-pitch :: Source -> StateVar ALfloat
-pitch = makeSourceStateVar dictALfloat GetPitch
-
---------------------------------------------------------------------------------
--- $DirectionAndCone
--- Each source can be directional, depending on the settings for 'coneAngles'.
--- There are three zones defined: the inner cone, the outside zone, and the
--- transitional zone in between. The angle-dependent gain for a directional
--- source is constant inside the inner cone, and changes over the transitional
--- zone to the value specified outside the outer cone. 'sourceGain' is applied
--- for the inner cone, with an application selectable 'coneOuterGain' factor to
--- define the gain in the outer zone. In the transitional zone
--- implementation-dependent interpolation between 'sourceGain' and 'sourceGain'
--- times 'coneOuterGain' is applied.
-
---------------------------------------------------------------------------------
-
--- | If 'direction' does not contain the zero vector ('Vector3' 0 0 0), the
--- source is directional. The sound emission is presumed to be symmetric around
--- the direction vector (cylinder symmetry). Sources are not oriented in full 3
--- degrees of freedom, only two angles are effectively needed.
---
--- The zero vector is the initial value, indicating that a source is not
--- directional. Specifying a non-zero vector will make the source directional.
--- Specifying a zero vector for a directional source will effectively mark it as
--- nondirectional.
-
-direction :: Source -> StateVar (Vector3 ALfloat)
-direction = makeSourceStateVar dictVector3ALfloat GetDirection
-
--- | 'coneAngles' contains the inner and outer angles of the sound cone, in
--- degrees. The default of 360 for the inner cone angle means that it covers the
--- entire world, which is equivalent to an omni-directional source. The default
--- of 360 for the outer cone angle means that it covers the entire world. If the
--- inner angle is also 360, then the zone for angle-dependent attenuation is
--- zero.
-
-coneAngles :: Source -> StateVar (ALfloat, ALfloat)
-coneAngles source =
-   pairStateVars
-      (makeSourceStateVar dictALfloat GetConeInnerAngle source)
-      (makeSourceStateVar dictALfloat GetConeOuterAngle source)
-
--- | 'coneOuterGain' contains the factor with which 'sourceGain' is multiplied
--- to determine the effective gain outside the cone defined by the outer angle.
--- The effective gain applied outside the outer cone is 'sourceGain' times
--- 'coneOuterGain'. Changing 'sourceGain' affects all directions, i.e. the
--- source is attenuated in all directions, for any position of the listener. The
--- application has to change 'coneOuterGain' as well if a different behavior is
--- desired.
-
-coneOuterGain :: Source -> StateVar Gain
-coneOuterGain = makeSourceStateVar dictALfloat GetConeOuterGain
-
---------------------------------------------------------------------------------
-
--- | 'secOffset' contains the playback position, expressed in seconds (the value
--- will loop back to zero for looping sources).
---
--- When setting 'secOffset' on a source which is already playing, the playback
--- will jump to the new offset unless the new offset is out of range, in which
--- case an 'ALInvalidValue' error is set. If the source is not playing, then the
--- offset will be applied on the next 'play' call.
---
--- The position is relative to the beginning of all the queued buffers for the
--- source, and any queued buffers traversed by a set call will be marked as
--- processed.
---
--- This value is based on byte position, so a pitch-shifted source will have an
--- exaggerated playback speed. For example, you can be 0.5 seconds into a buffer
--- having taken only 0.25 seconds to get there if the pitch is set to 2.
-
-secOffset :: Source -> StateVar ALfloat
-secOffset = makeSourceStateVar dictALfloat GetSecOffset
-
--- | 'sampleOffset' contains the playback position, expressed in samples (the
--- value will loop back to zero for looping sources). For a compressed format,
--- this value will represent an exact offset within the uncompressed data.
--- 
--- When setting 'sampleOffset' on a source which is already playing, the
--- playback will jump to the new offset unless the new offset is out of range,
--- in which case an 'ALInvalidValue' error is set. If the source is not playing,
--- then the offset will be applied on the next 'play' call. A 'stop', 'rewind',
--- or a second 'play' call will reset the offset to the beginning of the buffer.
--- 
--- The position is relative to the beginning of all the queued buffers for the
--- source, and any queued buffers traversed by a set call will be marked as
--- processed.
-
-sampleOffset :: Source -> StateVar ALint
-sampleOffset = makeSourceStateVar dictALint GetSampleOffset
-
--- | 'byteOffset' contains the playback position, expressed in bytes (the value
--- will loop back to zero for looping sources). For a compressed format, this
--- value may represent an approximate offset within the compressed data buffer.
--- 
--- When setting 'byteOffset' on a source which is already playing, the playback
--- will jump to the new offset unless the new offset is out of range, in which
--- case an 'ALInvalidValue' error is set. If the source is not playing, then the
--- offset will be applied on the next 'play' call. A 'stop', 'rewind', or a
--- second 'play' call will reset the offset to the beginning of the buffer.
--- 
--- The position is relative to the beginning of all the queued buffers for the
--- source, and any queued buffers traversed by a set call will be marked as
--- processed.
-
-byteOffset :: Source -> StateVar ALint
-byteOffset = makeSourceStateVar dictALint GetByteOffset
-
---------------------------------------------------------------------------------
-
-pairStateVars :: StateVar a -> StateVar b -> StateVar (a,b)
-pairStateVars var1 var2 =
-   makeStateVar
-      (liftM2 (,) (get var1) (get var2))
-      (\(val1,val2) -> do var1 $= val1; var2 $= val2)
-
-data Dictionary a b c = Dictionary {
-   alGetter  :: Source -> ALenum -> Ptr b -> IO (),
-   alSetter  :: Source -> ALenum -> Ptr b -> IO (),
-   size      :: Int,
-   peekSize  :: Ptr b -> IO a,
-   marshal   :: a -> c }
-
-dictALint :: Dictionary ALint ALint ALint
-dictALint = Dictionary {
-   alGetter  = alGetSourceiv,
-   alSetter  = alSourceiv,
-   size      = 1,
-   peekSize  = peek1 id,
-   marshal   = id }
-
-dictALfloat :: Dictionary ALfloat ALfloat ALfloat
-dictALfloat = Dictionary {
-   alGetter  = alGetSourcefv,
-   alSetter  = alSourcefv,
-   size      = 1,
-   peekSize  = peek1 id,
-   marshal   = id }
-
-dictSourceRelative :: Dictionary SourceRelative ALint ALint
-dictSourceRelative = Dictionary {
-   alGetter  = alGetSourceiv,
-   alSetter  = alSourceiv,
-   size      = 1,
-   peekSize  = peek1 (unmarshalSourceRelative . unmarshalALboolean . fromIntegral),
-   marshal   = fromIntegral . marshalALboolean . marshalSourceRelative }
-
-dictSourceType :: Dictionary SourceType ALint ALint
-dictSourceType = Dictionary {
-   alGetter  = alGetSourceiv,
-   alSetter  = undefined,
-   size      = 1,
-   peekSize  = peek1 unmarshalSourceType,
-   marshal   = undefined }
-
-dictLoopingMode :: Dictionary LoopingMode ALint ALint
-dictLoopingMode = Dictionary {
-   alGetter  = alGetSourceiv,
-   alSetter  = alSourceiv,
-   size      = 1,
-   peekSize  = peek1 (unmarshalLoopingMode . unmarshalALboolean . fromIntegral),
-   marshal   = fromIntegral . marshalALboolean . marshalLoopingMode }
-
-dictSourceState :: Dictionary SourceState ALint ALint
-dictSourceState = Dictionary {
-   alGetter  = alGetSourceiv,
-   alSetter  = undefined,
-   size      = 1,
-   peekSize  = peek1 unmarshalSourceState,
-   marshal   = undefined }
-
-dictVertex3ALfloat :: Dictionary (Vertex3 ALfloat) ALfloat (Vertex3 ALfloat)
-dictVertex3ALfloat = Dictionary {
-   alGetter  = alGetSourcefv,
-   alSetter  = alSourcefv,
-   size      = 3,
-   peekSize  = peek3 Vertex3,
-   marshal   = id }
-
-dictVector3ALfloat :: Dictionary (Vector3 ALfloat) ALfloat (Vector3 ALfloat)
-dictVector3ALfloat = Dictionary {
-   alGetter  = alGetSourcefv,
-   alSetter  = alSourcefv,
-   size      = 3,
-   peekSize  = peek3 Vector3,
-   marshal   = id }
-
-dictMaybeBuffer :: Dictionary (Maybe Buffer) ALint ALint
-dictMaybeBuffer = Dictionary {
-   alGetter  = alGetSourceiv,
-   alSetter  = alSourceiv,
-   size      = 1,
-   peekSize  = peek1 (unmarshalBuffer . fromIntegral),
-   marshal   = fromIntegral . marshalBuffer }
-
-makeGetter :: Storable b => Dictionary a b c -> GetPName -> Source -> IO a
-makeGetter dict name source =
-   allocaArray (size dict) $ \buf -> do
-      alGetter dict source (marshalGetPName name) buf
-      peekSize dict buf
-
-makeSetter :: Storable c => Dictionary a b c -> GetPName -> Source -> a -> IO ()
-makeSetter dict name source value =
-   with (marshal dict value) $
-      alSetter dict source (marshalGetPName name) . castPtr
-
-makeSourceStateVar ::
-   (Storable b, Storable c) =>
-   Dictionary a b c -> GetPName -> Source -> StateVar a
-makeSourceStateVar dict name source =
-   makeStateVar
-      (makeGetter dict name source)
-      (makeSetter dict name source)
-
-makeSourceGettableStateVar ::
-   (Storable b, Storable c) =>
-   Dictionary a b c -> GetPName -> Source -> GettableStateVar a
-makeSourceGettableStateVar dict name source =
-   makeGettableStateVar
-      (makeGetter dict name source)
-
---------------------------------------------------------------------------------
-
-foreign import ccall unsafe "alGetSourcefv"
-   alGetSourcefv :: Source -> ALenum -> Ptr ALfloat -> IO ()
-
-foreign import ccall unsafe "alSourcefv"
-   alSourcefv :: Source -> ALenum -> Ptr ALfloat -> IO ()
-
-foreign import ccall unsafe "alGetSourceiv"
-   alGetSourceiv :: Source ->  ALenum -> Ptr ALint -> IO ()
-
--- Note: Older OpenAL implementations have no alSourceiv, so we emulate it here.
-alSourceiv :: Source -> ALenum -> Ptr ALint -> IO ()
-alSourceiv source n buf =  peek buf >>= alSourcei source n
-
-foreign import ccall unsafe "alSourcei"
-   alSourcei :: Source -> ALenum -> ALint -> IO ()
-
---------------------------------------------------------------------------------
--- $QueuingBuffersWithASource
--- OpenAL does not specify a built-in streaming mechanism. There is no mechanism
--- to stream data into a buffer object. Instead, the API has a more flexible and
--- versatile mechanism to queue buffers for sources. There are many ways to use
--- this feature, with streaming being only one of them.
---
--- Streaming is replaced by queuing static buffers. This effectively moves any
--- multi-buffer caching into the application and allows the application to
--- select how many buffers it wants to use, the size of the buffers, and whether
--- these are re-used in cycle, pooled, or thrown away.
---
--- Looping (over a finite number of repetitions) can be implemented by
--- explicitly repeating buffers in the queue. Infinite loops can (theoretically)
--- be accomplished by sufficiently large repetition counters. If only a single
--- buffer is supposed to be repeated infinitely, using the respective source
--- attribute 'loopingMode' is recommended.
---
--- Loop Points for restricted looping inside a buffer can in many cases be
--- replaced by splitting the sample into several buffers and queuing the sample
--- fragments (including repetitions) accordingly.
---
--- Buffers can be queued, unqueued after they have been used, and either be
--- deleted, or refilled and queued again. Splitting large samples over several
--- buffers maintained in a queue has distinct advantages over approaches that
--- require explicit management of samples and sample indices.
-
---------------------------------------------------------------------------------
-
--- | The application can queue up one or multiple buffer names using
--- 'queueBuffers'. The buffers will be queued in the sequence in which they
--- appear in the list.
---
--- This command is legal on a source in any playback state (to allow for
--- streaming, queuing has to be possible on a 'Playing' source).
---
--- All buffers in a queue must have the same format and attributes. An attempt
--- to mix formats or other buffer attributes will result in a failure and an
--- 'ALInvalidValue' error will be thrown. If the queue operation fails, the source
--- queue will remain unchanged (even if some of the buffers could have been
--- queued).
-
-queueBuffers :: Source -> [Buffer] -> IO ()
-queueBuffers = withArraySizei . alSourceQueueBuffers
-
-withArraySizei :: Storable a => (ALsizei -> Ptr a -> IO ()) -> [a] -> IO ()
-withArraySizei f xs = withArrayLen xs $ f . fromIntegral
-
-foreign import ccall unsafe "alSourceQueueBuffers"
-   alSourceQueueBuffers :: Source -> ALsizei -> Ptr Buffer -> IO ()
-
---------------------------------------------------------------------------------
-
--- | Once a queue entry for a buffer has been appended to a queue and is pending
--- processing, it should not be changed. Removal of a given queue entry is not
--- possible unless either the source is stopped (in which case then entire queue
--- is considered processed), or if the queue entry has already been processed
--- ('Playing' or 'Paused' source). A playing source will enter the 'Stopped'
--- state if it completes playback of the last buffer in its queue (the same
--- behavior as when a single buffer has been attached to a source and has
--- finished playback).
---
--- The 'unqueueBuffers' command removes a number of buffers entries that have
--- finished processing from the queue, returning the buffers that were unqueued.
--- The operation will fail with an 'ALInvalidValue' error if more buffers are
--- requested than available, leaving the destination arguments unchanged.
-
-unqueueBuffers :: Source -> ALsizei -> IO [Buffer]
-unqueueBuffers src n = allocaArray (fromIntegral n) $ \p -> do
-    alSourceUnqueueBuffers src n p
-    peekArray (fromIntegral n) p
-
-foreign import ccall unsafe "alSourceUnqueueBuffers"
-   alSourceUnqueueBuffers :: Source -> ALsizei -> Ptr Buffer -> IO ()
-
---------------------------------------------------------------------------------
--- $ManagingSourceExecution
--- The execution state of a source can be queried. OpenAL provides a set of
--- functions that initiate state transitions causing sources to start and stop
--- execution.
-
---------------------------------------------------------------------------------
-
--- | Contains the current execution state of the given source. The initial state
--- of any source is 'Initial'.
---
--- Note that the 'Initial' state is not necessarily identical to the initial
--- state in which a source is created, because the other source attributes are
--- not automatically reset to their initial values. 'Initial' merely indicates
--- that the source can be executed using the 'play' command. A 'Stopped' or
--- 'Initial' source can be reset into the default configuration by using a
--- sequence of source commands as necessary. As the application has to specify
--- all relevant state anyway to create a useful source configuration, no reset
--- command is provided.
-
-sourceState :: Source -> GettableStateVar SourceState
-sourceState source =
-   makeGettableStateVar
-      (makeGetter dictSourceState GetSourceState source)
-
---------------------------------------------------------------------------------
-
--- | 'play' applied to an 'Initial' source will promote the source to 'Playing',
--- thus the data found in the buffer will be fed into the processing, starting
--- at the beginning. 'play' applied to a 'Playing' source will restart the
--- source from the beginning. It will not affect the configuration, and will
--- leave the source in 'Playing' state, but reset the sampling offset to the
--- beginning. 'play' applied to a 'Paused' source will resume processing using
--- the source state as preserved at the 'pause' operation. 'play' applied to a
--- 'Stopped' source will propagate it to 'Initial' then to 'Playing'
--- immediately.
-
-play :: [Source] -> IO ()
-play = withArraySizei alSourcePlayv
-
-foreign import ccall unsafe "alSourcePlayv"
-   alSourcePlayv :: ALsizei -> Ptr Source -> IO ()
-
--- | 'pause' applied to an 'Initial' source is a legal NOP. 'pause' applied to a
--- 'Playing' source will change its state to 'Paused'. The source is exempt from
--- processing, its current state is preserved. 'pause' applied to a 'Paused'
--- source is a legal NOP. 'pause' applied to a 'Stopped' source is a legal NOP.
-
-pause :: [Source] -> IO ()
-pause = withArraySizei alSourcePausev
-
-foreign import ccall unsafe "alSourcePausev"
-   alSourcePausev :: ALsizei -> Ptr Source -> IO ()
-
--- | 'stop' applied to an 'Initial' source is a legal NOP. 'stop' applied to a
--- 'Playing' source will change its state to 'Stopped'. The source is exempt
--- from processing, its current state is preserved. 'stop' applied to a 'Paused'
--- source will change its state to 'Stopped', with the same consequences as on a
--- 'Playing' source. 'stop' applied to a 'Stopped' source is a legal NOP.
-
-stop :: [Source] -> IO ()
-stop = withArraySizei alSourceStopv
-
-foreign import ccall unsafe "alSourceStopv"
-   alSourceStopv :: ALsizei -> Ptr Source -> IO ()
-
--- | 'rewind' applied to an 'Initial' source is a legal NOP. 'rewind' applied to
--- a 'Playing' source will change its state to 'Stopped' then 'Initial'. The
--- source is exempt from processing: its current state is preserved, with the
--- exception of the sampling offset, which is reset to the beginning.  'rewind'
--- applied to a 'Paused' source will change its state to 'Initial', with the
--- same consequences as on a 'Playing' source.  'rewind' applied to an 'Stopped'
--- source promotes the source to 'Initial', resetting the sampling offset to the
--- beginning.
-
-rewind :: [Source] -> IO ()
-rewind = withArraySizei alSourceRewindv
-
-foreign import ccall unsafe "alSourceRewindv"
-   alSourceRewindv :: ALsizei -> Ptr Source -> IO ()
diff --git a/Sound/OpenAL/AL/SourceState.hs b/Sound/OpenAL/AL/SourceState.hs
deleted file mode 100644
--- a/Sound/OpenAL/AL/SourceState.hs
+++ /dev/null
@@ -1,46 +0,0 @@
-{-# OPTIONS_HADDOCK hide #-}
---------------------------------------------------------------------------------
--- |
--- Module      :  Sound.OpenAL.AL.SourceState
--- Copyright   :  (c) Sven Panne 2003-2013
--- License     :  BSD3
--- 
--- Maintainer  :  Sven Panne <svenpanne@gmail.com>
--- Stability   :  stable
--- Portability :  portable
---
---------------------------------------------------------------------------------
-
-module Sound.OpenAL.AL.SourceState (
-   SourceState(..), unmarshalSourceState
-) where
-
-import Sound.OpenAL.AL.BasicTypes ( ALint )
-import Sound.OpenAL.Constants ( al_INITIAL, al_PLAYING, al_PAUSED, al_STOPPED )
-
---------------------------------------------------------------------------------
-
--- | Each source can be in one of four possible execution states: 'Initial',
--- 'Playing', 'Paused', 'Stopped'. Sources that are either 'Playing' or 'Paused'
--- are considered active. Sources that are 'Stopped' or 'Initial' are considered
--- inactive. Only 'Playing' sources are included in the processing. The
--- implementation is free to skip those processing stages for sources that have
--- no effect on the output (e.g. mixing for a source muted by zero gain, but not
--- sample offset increments). Depending on the current state of a source certain
--- (e.g. repeated) state transition commands are legal NOPs: they will be
--- ignored, no error is generated.
-
-data SourceState =
-     Initial
-   | Playing
-   | Paused
-   | Stopped
-   deriving ( Eq, Ord, Show )
-
-unmarshalSourceState :: ALint -> SourceState
-unmarshalSourceState x
-   | x == al_INITIAL = Initial
-   | x == al_PLAYING = Playing
-   | x == al_PAUSED = Paused
-   | x == al_STOPPED = Stopped
-   | otherwise = error ("unmarshalSourceState: illegal value " ++ show x)
diff --git a/Sound/OpenAL/AL/String.hs b/Sound/OpenAL/AL/String.hs
deleted file mode 100644
--- a/Sound/OpenAL/AL/String.hs
+++ /dev/null
@@ -1,31 +0,0 @@
-{-# OPTIONS_HADDOCK hide #-}
---------------------------------------------------------------------------------
--- |
--- Module      :  Sound.OpenAL.AL.String
--- Copyright   :  (c) Sven Panne 2003-2013
--- License     :  BSD3
--- 
--- Maintainer  :  Sven Panne <svenpanne@gmail.com>
--- Stability   :  stable
--- Portability :  portable
---
---------------------------------------------------------------------------------
-
-module Sound.OpenAL.AL.String (
-   withALString, peekALString
-) where
-
-import Foreign.C.String ( withCString, peekCString )
-import Foreign.Ptr ( Ptr, castPtr )
-import Sound.OpenAL.AL.BasicTypes ( ALchar )
-
---------------------------------------------------------------------------------
-
--- AL uses "Ptr ALchar" instead of "CString" for strings, so some wrappers
--- are quite handy.
-
-withALString :: String -> (Ptr ALchar -> IO a) -> IO a
-withALString str action = withCString str (action . castPtr)
-
-peekALString :: Ptr ALchar -> IO String
-peekALString = peekCString . castPtr
diff --git a/Sound/OpenAL/AL/StringQueries.hs b/Sound/OpenAL/AL/StringQueries.hs
deleted file mode 100644
--- a/Sound/OpenAL/AL/StringQueries.hs
+++ /dev/null
@@ -1,33 +0,0 @@
---------------------------------------------------------------------------------
--- |
--- Module      :  Sound.OpenAL.AL.StringQueries
--- Copyright   :  (c) Sven Panne 2003-2013
--- License     :  BSD3
--- 
--- Maintainer  :  Sven Panne <svenpanne@gmail.com>
--- Stability   :  stable
--- Portability :  portable
---
--- This module corresponds to section 3.1.2 (String Queries) of the OpenAL
--- Specification and Reference (version 1.1).
---
---------------------------------------------------------------------------------
-
-module Sound.OpenAL.AL.StringQueries (
-   alVendor, alRenderer
-) where
-
-import Graphics.Rendering.OpenGL.GL.StateVar
-import Sound.OpenAL.AL.QueryUtils ( StringName(..), getString )
-
---------------------------------------------------------------------------------
-
--- | Contains the name of the vendor.
-
-alVendor :: GettableStateVar String
-alVendor = makeGettableStateVar (getString Vendor)
-
--- | Contains information about the specific renderer.
-
-alRenderer :: GettableStateVar String
-alRenderer = makeGettableStateVar (getString Renderer)
diff --git a/Sound/OpenAL/ALC.hs b/Sound/OpenAL/ALC.hs
deleted file mode 100644
--- a/Sound/OpenAL/ALC.hs
+++ /dev/null
@@ -1,35 +0,0 @@
---------------------------------------------------------------------------------
--- |
--- Module      :  Sound.OpenAL.ALC
--- Copyright   :  (c) Sven Panne 2003-2013
--- License     :  BSD3
--- 
--- Maintainer  :  Sven Panne <svenpanne@gmail.com>
--- Stability   :  stable
--- Portability :  portable
---
--- This module corresponds to chapter 6 (AL Contexts and the ALC API) of the
--- OpenAL Specification and Reference (version 1.1).
---
--- ALC is a portable API for managing OpenAL contexts, including resource
--- sharing, locking, and unlocking. Within the core AL API the existence of a
--- context is implied, but the context is not exposed. The context encapsulates
--- the state of a given instance of the AL state machine.
---
---------------------------------------------------------------------------------
-
-module Sound.OpenAL.ALC (
-   module Sound.OpenAL.ALC.BasicTypes,
-   module Sound.OpenAL.ALC.Device,
-   module Sound.OpenAL.ALC.Context,
-   module Sound.OpenAL.ALC.Extensions,
-   module Sound.OpenAL.ALC.Errors,
-   module Sound.OpenAL.ALC.Capture
-) where
-
-import Sound.OpenAL.ALC.BasicTypes
-import Sound.OpenAL.ALC.Device
-import Sound.OpenAL.ALC.Context
-import Sound.OpenAL.ALC.Extensions
-import Sound.OpenAL.ALC.Errors
-import Sound.OpenAL.ALC.Capture
diff --git a/Sound/OpenAL/ALC/ALCboolean.hs b/Sound/OpenAL/ALC/ALCboolean.hs
deleted file mode 100644
--- a/Sound/OpenAL/ALC/ALCboolean.hs
+++ /dev/null
@@ -1,30 +0,0 @@
-{-# OPTIONS_HADDOCK hide #-}
---------------------------------------------------------------------------------
--- |
--- Module      :  Sound.OpenAL.ALC.ALCboolean
--- Copyright   :  (c) Sven Panne 2003-2013
--- License     :  BSD3
--- 
--- Maintainer  :  Sven Panne <svenpanne@gmail.com>
--- Stability   :  stable
--- Portability :  portable
---
--- This is a purely internal module for (un-)marshaling ALCboolean.
---
---------------------------------------------------------------------------------
-
-module Sound.OpenAL.ALC.ALCboolean (
-   marshalALCboolean, unmarshalALCboolean
-) where
-
-import Sound.OpenAL.ALC.BasicTypes ( ALCboolean )
-import Sound.OpenAL.Constants ( alc_FALSE, alc_TRUE )
-
---------------------------------------------------------------------------------
-
-marshalALCboolean :: Bool -> ALCboolean
-marshalALCboolean False = alc_FALSE
-marshalALCboolean True  = alc_TRUE
-
-unmarshalALCboolean :: ALCboolean -> Bool
-unmarshalALCboolean = (/= alc_FALSE)
diff --git a/Sound/OpenAL/ALC/BasicTypes.hs b/Sound/OpenAL/ALC/BasicTypes.hs
deleted file mode 100644
--- a/Sound/OpenAL/ALC/BasicTypes.hs
+++ /dev/null
@@ -1,24 +0,0 @@
---------------------------------------------------------------------------------
--- |
--- Module      :  Sound.OpenAL.ALC.BasicTypes
--- Copyright   :  (c) Sven Panne 2003-2013
--- License     :  BSD3
--- 
--- Maintainer  :  Sven Panne <svenpanne@gmail.com>
--- Stability   :  stable
--- Portability :  portable
---
--- This module corresponds to the introductory parts of chapter 6 (AL Contexts
--- and the ALC API) of the OpenAL Specification and Reference (version 1.1).
---
--- The context API makes use of ALC types which are defined separately from the
--- AL types - there is an 'ALCboolean', 'ALCchar', etc.
---
---------------------------------------------------------------------------------
-
-module Sound.OpenAL.ALC.BasicTypes (
-   ALCboolean, ALCchar, ALCbyte, ALCubyte, ALCshort, ALCushort, ALCint, ALCuint,
-   ALCsizei, ALCenum, ALCfloat, ALCdouble
-) where
-
-import Sound.OpenAL.Config
diff --git a/Sound/OpenAL/ALC/Capture.hs b/Sound/OpenAL/ALC/Capture.hs
deleted file mode 100644
--- a/Sound/OpenAL/ALC/Capture.hs
+++ /dev/null
@@ -1,139 +0,0 @@
-{-# LANGUAGE ForeignFunctionInterface #-}
---------------------------------------------------------------------------------
--- |
--- Module      :  Sound.OpenAL.ALC.Capture
--- Copyright   :  (c) Sven Panne 2003-2013
--- License     :  BSD3
--- 
--- Maintainer  :  Sven Panne <svenpanne@gmail.com>
--- Stability   :  stable
--- Portability :  portable
---
--- This module corresponds to section 6.4.2. (Capture) of the OpenAL
--- Specification and Reference (version 1.1).
---
---------------------------------------------------------------------------------
-
-module Sound.OpenAL.ALC.Capture (
-   NumSamples, captureOpenDevice, captureStart, captureNumSamples,
-   captureSamples, captureStop, captureCloseDevice,
-   captureDefaultDeviceSpecifier, captureDeviceSpecifier,
-   allCaptureDeviceSpecifiers
-) where
-
-import Graphics.Rendering.OpenGL.GL.StateVar
-import Foreign.C.Types
-import Foreign.Ptr ( Ptr, nullPtr, FunPtr )
-import Sound.OpenAL.AL.Buffer ( Format )
-import Sound.OpenAL.AL.Format ( marshalFormat )
-import Sound.OpenAL.ALC.ALCboolean ( unmarshalALCboolean )
-import Sound.OpenAL.ALC.BasicTypes (
-   ALCchar, ALCuint, ALCenum, ALCsizei, ALCboolean )
-import Sound.OpenAL.ALC.Context ( Frequency )
-import Sound.OpenAL.ALC.Device ( Device )
-import Sound.OpenAL.ALC.Extensions ( alcProcAddress )
-import Sound.OpenAL.ALC.QueryUtils ( IntQuery(..), getInteger )
-import Sound.OpenAL.ALC.QueryUtils (
-   StringQuery(..), getString, getStringRaw, alcIsExtensionPresent )
-import Sound.OpenAL.ALC.String ( withALCString, peekALCStrings )
-import Sound.OpenAL.Config ( ALCdevice(..), marshalDevice, unmarshalDevice )
-
---------------------------------------------------------------------------------
-
-type NumSamples = ALCsizei
-
---------------------------------------------------------------------------------
-
-type Invoker a = FunPtr a -> a
-
-getCaptureFunc :: String -> IO (FunPtr a)
-getCaptureFunc = get . alcProcAddress Nothing
-
---------------------------------------------------------------------------------
-
-captureOpenDevice ::
-   Maybe String -> Frequency -> Format -> NumSamples -> IO (Maybe Device)
-captureOpenDevice maybeDeviceSpec frequency format size = do
-   funPtr <- getCaptureFunc "alcCaptureOpenDevice"
-   let open deviceSpec =
-          invokeCaptureOpenDevice funPtr deviceSpec (round frequency)
-                                  (fromIntegral (marshalFormat format)) size
-   fmap unmarshalDevice $
-      (maybe (open nullPtr)   -- use preferred device
-             (flip withALCString open)
-             maybeDeviceSpec)
-
-foreign import ccall unsafe "dynamic"
-   invokeCaptureOpenDevice :: Invoker (Ptr ALCchar -> ALCuint -> ALCenum -> ALCsizei -> IO ALCdevice)
-
---------------------------------------------------------------------------------
-
-captureStart :: Device -> IO ()
-captureStart = captureStartStop "alcCaptureStart"
-
-captureStartStop :: String -> Device -> IO ()
-captureStartStop funName device = do
-   funPtr <- getCaptureFunc funName
-   invokeCaptureStartStop funPtr (marshalDevice device)
-
-foreign import ccall unsafe "dynamic"
-   invokeCaptureStartStop :: Invoker (ALCdevice -> IO ()) 
-
---------------------------------------------------------------------------------
-
-captureNumSamples :: Device -> GettableStateVar NumSamples
-captureNumSamples device = makeGettableStateVar $
-   fmap fromIntegral (getInteger (Just device) CaptureSamples)
-
---------------------------------------------------------------------------------
-
-captureSamples :: Device -> Ptr a -> NumSamples -> IO ()
-captureSamples device buf n = do
-   funPtr <- getCaptureFunc "alcCaptureSamples"
-   invokeCaptureSamples funPtr (marshalDevice device) buf n
-
-foreign import ccall unsafe "dynamic"
-   invokeCaptureSamples :: Invoker (ALCdevice -> Ptr a -> NumSamples -> IO ())
-
---------------------------------------------------------------------------------
-
-captureStop :: Device -> IO ()
-captureStop = captureStartStop "alcCaptureStop"
-
---------------------------------------------------------------------------------
-
-captureCloseDevice :: Device -> IO Bool
-captureCloseDevice device = do
-   funPtr <- getCaptureFunc "alcCaptureCloseDevice"
-   fmap unmarshalALCboolean .
-      invokeCaptureCloseDevice funPtr . marshalDevice $ device
-
-foreign import ccall unsafe "dynamic"
-   invokeCaptureCloseDevice :: Invoker (ALCdevice -> IO ALCboolean) 
-
---------------------------------------------------------------------------------
-
--- | Contains the name of the default capture device.
-
-captureDefaultDeviceSpecifier :: GettableStateVar String
-captureDefaultDeviceSpecifier = makeGettableStateVar $
-   getString Nothing CaptureDefaultDeviceSpecifier
-
---------------------------------------------------------------------------------
-
--- | Contains the specifier string for the given capture device.
-
-captureDeviceSpecifier :: Device -> GettableStateVar String
-captureDeviceSpecifier device = makeGettableStateVar $
-   getString (Just device) CaptureDeviceSpecifier
-
---------------------------------------------------------------------------------
-
--- | Contains a list of specifiers for all available capture devices.
-
-allCaptureDeviceSpecifiers :: GettableStateVar [String]
-allCaptureDeviceSpecifiers = makeGettableStateVar $ do
-   enumExtPresent <- get (alcIsExtensionPresent Nothing "ALC_ENUMERATION_EXT")
-   if enumExtPresent
-      then peekALCStrings =<< getStringRaw Nothing CaptureDeviceSpecifier
-      else fmap (\s -> [s]) $ get captureDefaultDeviceSpecifier
diff --git a/Sound/OpenAL/ALC/Context.hs b/Sound/OpenAL/ALC/Context.hs
deleted file mode 100644
--- a/Sound/OpenAL/ALC/Context.hs
+++ /dev/null
@@ -1,195 +0,0 @@
-{-# LANGUAGE ForeignFunctionInterface #-}
-{-# OPTIONS_GHC -fno-warn-unused-imports #-}
---------------------------------------------------------------------------------
--- |
--- Module      :  Sound.OpenAL.ALC.Context
--- Copyright   :  (c) Sven Panne 2003-2013
--- License     :  BSD3
--- 
--- Maintainer  :  Sven Panne <svenpanne@gmail.com>
--- Stability   :  stable
--- Portability :  portable
---
--- This module corresponds to section 6.2 (Managing Rendering Contexts) of the
--- OpenAL Specification and Reference (version 1.1).
---
--- All operations of the AL core API affect a current AL context. Within the
--- scope of AL, the ALC is implied - it is not visible as a handle or function
--- parameter. Only one AL Context per process can be current at a time.
--- Applications maintaining multiple AL Contexts, whether threaded or not,
--- have to set the current context accordingly. Applications can have multiple
--- threads that share one more or contexts. In other words, AL and ALC are
--- threadsafe.
---
---------------------------------------------------------------------------------
-
-module Sound.OpenAL.ALC.Context (
-   Frequency, ContextAttribute(..), Context, createContext, currentContext,
-   processContext, suspendContext, destroyContext, contextsDevice, allAttributes
-) where
-
-import Foreign.Marshal.Array
-import Foreign.Ptr
-import Graphics.Rendering.OpenGL.GL.StateVar
-import Sound.OpenAL.ALC.ALCboolean
-import Sound.OpenAL.ALC.BasicTypes
-import Sound.OpenAL.ALC.Device
-import Sound.OpenAL.ALC.QueryUtils
-import Sound.OpenAL.Config
-import Sound.OpenAL.Constants
-
--- For Haddock only.
-import Sound.OpenAL.ALC.Errors
-
---------------------------------------------------------------------------------
-
--- | Frequency, specified in samples per second, i.e. units of Hertz \[Hz\].
--- Note that the underlying OpenAL API currently uses integral frequencies
--- only, but we want to mirror physical reality here more closely.
-
-type Frequency = Float
-
---------------------------------------------------------------------------------
-
--- | The application can choose to specify certain attributes for a context at
--- context-creation time. Attributes not specified explicitly are set to
--- implementation dependent defaults.
-
-data ContextAttribute =
-     Frequency Frequency   -- ^ Frequency for mixing output buffer, in units of
-                           --   Hz
-   | Refresh Frequency     -- ^ Refresh intervals, in units of Hz
-   | Sync Bool             -- ^ Flag, indicating a synchronous context
-   | MonoSources Int       -- ^ A hint indicating how many sources should be
-                           --   capable of supporting mono data
-   | StereoSources Int     -- ^ A hint indicating how many sources should be
-                           --   capable of supporting stereo data
-   deriving ( Eq, Ord, Show )
-
-marshalContextAttribute :: ContextAttribute -> (ALCint,ALCint)
-marshalContextAttribute a = case a of
-   Frequency f -> (alc_FREQUENCY, round f)
-   Refresh r -> (alc_REFRESH, round r)
-   Sync s -> (alc_SYNC, fromIntegral (marshalALCboolean s))
-   MonoSources m -> (alc_MONO_SOURCES, fromIntegral m)
-   StereoSources s -> (alc_STEREO_SOURCES, fromIntegral s)
-
-unmarshalContextAttribute :: (ALCint,ALCint) -> ContextAttribute
-unmarshalContextAttribute a@(x,y)
-   | x == alc_FREQUENCY = Frequency (fromIntegral y)
-   | x == alc_REFRESH = Refresh (fromIntegral y)
-   | x == alc_SYNC = Sync (unmarshalALCboolean (fromIntegral y))
-   | x == alc_MONO_SOURCES = MonoSources (fromIntegral y)
-   | x == alc_STEREO_SOURCES = StereoSources (fromIntegral y)
-   | otherwise = error ("unmarshalContextAttribute: illegal value " ++ show a)
-
---------------------------------------------------------------------------------
-
--- | Create a context for a given device and given attributes. Context creation
--- will fail in the following cases: a) if the application requests attributes
--- that, by themselves, can not be provided b) if the combination of specified
--- attributes can not be provided c) if a specified attribute, or the
--- combination of attributes, does not match the default values for unspecified
--- attributes If context creation fails, 'Nothing' will be returned, otherwise
--- 'Just' the new context. Note that 'createContext' does /not/ set the current
--- context, this must be done separately via 'currentContext'.
-
-createContext :: Device -> [ContextAttribute] -> IO (Maybe Context)
-createContext device attributes = do
-   let pairToList (key, value) = [key, value]
-       attrs = concatMap (pairToList . marshalContextAttribute) attributes
-   fmap unmarshalContext .
-      withArray0 0 attrs . alcCreateContext . marshalDevice $ device
-
-foreign import ccall unsafe "alcCreateContext"
-   alcCreateContext :: ALCdevice -> Ptr ALCint -> IO ALCcontext
-
---------------------------------------------------------------------------------
-
--- | Contains 'Just' the current context with respect to OpenAL operation, or
--- 'Nothing' if there is no current context. Setting it to the latter is useful
--- when shutting OpenAL down. The state variable applies to the device that the
--- context was created for. For each OS process (usually this means for each
--- application), only one context can be current at any given time. All AL
--- commands apply to the current context. Commands that affect objects shared
--- among contexts (e.g. buffers) have side effects on other contexts.
-
-currentContext :: StateVar (Maybe Context)
-currentContext = makeStateVar getCurrentContext makeContextCurrent
-
-getCurrentContext :: IO (Maybe Context)
-getCurrentContext = fmap unmarshalContext $ alcGetCurrentContext
-
-foreign import ccall unsafe "alcGetCurrentContext"
-   alcGetCurrentContext :: IO ALCcontext
-
-makeContextCurrent :: Maybe Context -> IO ()
-makeContextCurrent =
-   fmap (const ()) . alcMakeContextCurrent . marshalContext . maybe nullContext id
-
---------------------------------------------------------------------------------
-
--- | The current context is the only context accessible to state changes by AL
--- commands (aside from state changes affecting shared objects). However,
--- multiple contexts can be processed at the same time. To indicate that a
--- context should be processed (i.e. that internal execution state like offset
--- increments are supposed to be performed), the application has to use
--- 'processContext'. Repeated calls to 'processContext' are legal, and do not
--- affect a context that is already marked as processing. The default state of a
--- context created by 'createContext' is that it is processing.
-
-processContext :: Context -> IO ()
-processContext = fmap (const ()) . alcProcessContext . marshalContext
-
--- | The application can suspend any context from processing (including the
--- current one). To indicate that a context should be suspended from processing
--- (i.e. that internal execution state like offset increments is not supposed to
--- be changed), the application has to use 'suspendContext'. Repeated calls to
--- 'suspendContext' are legal, and do not affect a context that is already
--- marked as suspended.
-
-suspendContext :: Context -> IO ()
-suspendContext = alcSuspendContext . marshalContext
-
-foreign import ccall unsafe "alcSuspendContext"
-   alcSuspendContext :: ALCcontext -> IO ()
-
---------------------------------------------------------------------------------
-
--- | Destroy the given context. Note that the the correct way to destroy a
--- context is to first release it by setting 'currentContext' to
--- 'Nothing'. Applications should not attempt to destroy a current context,
--- doing so will not work and will result in an 'ALCInvalidOperation' error.
-
-destroyContext :: Context -> IO ()
-destroyContext = fmap (const ()) . alcDestroyContext . marshalContext
-
---------------------------------------------------------------------------------
-
--- | Contains 'Just' the device of the given context or 'Nothing' if the context
--- is invalid.
-
-contextsDevice :: Context -> GettableStateVar (Maybe Device)
-contextsDevice =
-   makeGettableStateVar .
-      fmap unmarshalDevice . alcGetContextsDevice . marshalContext
-
-foreign import ccall unsafe "alcGetContextsDevice"
-   alcGetContextsDevice :: ALCcontext -> IO ALCdevice
-
---------------------------------------------------------------------------------
-
--- | Contains the attribute list for the current context of the specified
--- device.
-
-allAttributes :: Device -> GettableStateVar [ContextAttribute]
-allAttributes device = makeGettableStateVar $ do
-   numALCints <- fmap fromIntegral $ getInteger (Just device) AttributesSize
-   fmap toContextAttributes $ getIntegerv (Just device) AllAttributes numALCints
-
-toContextAttributes :: [ALCint] -> [ContextAttribute]
-toContextAttributes xs = case xs of
-   [] -> []  -- should only happen when device and/or current context is invalid
-   (0:_) -> []
-   (x:y:rest) -> unmarshalContextAttribute (x,y) : toContextAttributes rest
-   _ -> error ("toContextAttributes: illegal value " ++ show xs)
diff --git a/Sound/OpenAL/ALC/Device.hs b/Sound/OpenAL/ALC/Device.hs
deleted file mode 100644
--- a/Sound/OpenAL/ALC/Device.hs
+++ /dev/null
@@ -1,223 +0,0 @@
-{-# LANGUAGE ForeignFunctionInterface #-}
---------------------------------------------------------------------------------
--- |
--- Module      :  Sound.OpenAL.ALC.Device
--- Copyright   :  (c) Sven Panne 2003-2013
--- License     :  BSD3
--- 
--- Maintainer  :  Sven Panne <svenpanne@gmail.com>
--- Stability   :  stable
--- Portability :  portable
---
--- This module corresponds to section 6.1 (Managing Devices) of the OpenAL
--- Specification and Reference (version 1.1).
---
--- ALC introduces the notion of a device. A device can be, depending on the
--- implementation, a hardware device, or a daemon\/OS service\/actual
--- server. This mechanism also permits different drivers (and hardware) to
--- coexist within the same system, as well as allowing several applications to
--- share system resources for audio, including a single hardware output
--- device. The details are left to the implementation, which has to map the
--- available backends to unique device specifiers.
---
---------------------------------------------------------------------------------
-
-module Sound.OpenAL.ALC.Device (
-   Device, openDevice, closeDevice,
-   defaultDeviceSpecifier, deviceSpecifier, allDeviceSpecifiers
-) where
-
-import Graphics.Rendering.OpenGL.GL.StateVar
-import Foreign.Ptr ( Ptr, nullPtr )
-import Foreign.Marshal.Utils ( maybePeek )
-import Sound.OpenAL.ALC.BasicTypes ( ALCchar )
-import Sound.OpenAL.ALC.QueryUtils (
-   StringQuery(..), getString, getStringRaw, alcIsExtensionPresent )
-import Sound.OpenAL.ALC.String ( withALCString, peekALCString, peekALCStrings )
-import Sound.OpenAL.Config (
-   Device, ALCdevice(..), unmarshalDevice, closeDevice )
-
---------------------------------------------------------------------------------
-
--- | 'openDevice' allows the application (i.e. the client program) to connect to
--- a device (i.e. the server). If the function returns 'Nothing', then no sound
--- driver\/device has been found. The argument to 'openDevice' specifies a
--- certain device or device configuration. If it is 'Nothing', the
--- implementation will provide an implementation specific default, see
--- 'defaultDeviceSpecifier'. Otherwise it is 'Just' an implementation-dependent
--- string. You can use 'allDeviceSpecifiers' to get a list of the known OpenAL
--- devices.
---
--- /Notes for Windows:/ There are 3 possible device strings, each having a
--- deprecated equivalent for legacy applications only:
---
--- * @\"Generic Hardware\"@ (legacy string: @\"DirectSound3D\"@)
---
--- * @\"Generic Software\"@ (legacy string: @\"DirectSound\"@)
---
--- * @\"Generic Software Fallback\"@ (legacy string: @\"MMSYSTEM\"@)
---
--- /Notes for Linux\/\*nix:/ If an @.openalrc@ file is present in the user\'s
--- home directory, it is loaded first, otherwise @\/etc\/openalrc@ is tried.
--- The bindings (if any) of @devices@, @direction@, @sampling-rate@, and
--- @speaker-num@ (see below) after loading one of these files take precedence
--- over any bindings done via the argument to 'openDevice'.
---
--- The syntax of these files is lisp-based and a sequence of expressions, where
--- an expression is one the following:
---
--- * A boolean value of the form @\#f@ or @\#t@, which evaluate to /false/ and
--- /true/, respectively.
---
--- * An non-negative integer value, i.e. a sequence of decimal digits,
--- evaluating to itself.
---
--- * A (signed) floating point value, as recoginzed by C\'s @atof()@, evaluating
--- to itself.
---
--- * A pointer value of the form @\#p/num/@, where /num/ can be an octal,
--- decimal or hexadecimal value, as recoginzed by C\`s @strtol()@, evaluating
--- to itself. This kind of expression is currently unused.
---
--- * A string, i.e. a sequence of printable\/whitespace characters between
--- double quotes, evaluating to itself.
---
--- * A symbol, i.e. a sequence of almost all characters which don\'t form a
--- simple expression like the ones mentioned below, e.g. @foo@, @bar1@, @3baz@,
--- ... The symbol evaluates to the value currently bound to it.
---
--- * A function application of the form @(/symbol/ /expression/...)@. The
--- function bound to the symbol is applied to the evaluated arguments.
--- 
--- * A quotation of the form @(quote /expression/)@ or @\'/expression/@,
--- evaluating to the unevaluated /expression/ itself.
---
--- * A definition of the form @(define /symbol/ /expression/)@, binding /symbol/
--- to the value of /expression/. The whole expression evaluates to the value of
--- /expression/, too.
---
--- * A conjunction of boolean expressions of the form @(and /expression/...)@.
--- Each /expression/ is evaluated in turn, and if one of them evaluates to
--- /false/, the value of the whole expression is /false/. Otherwise the value is
--- /true/.
---
--- * An extension loading mechanism of the form @(load-extension
--- /libraryName/)@, where /libraryName/ has to evaluate to a string. This tries
--- to load the dynamic library with up to 3 special entry points:
--- @alExtension_03282000@ (pointing to a mandatory NULL-terminated sequence of
--- pairs of pointers to names and extension functions), @alExtInit_03282000@ (an
--- optional initialization function), and @alExtFini_03282000@ (an optional
--- cleanup function). If the extension could be loaded successfully, the whole
--- expression evaluates to /true/, otherwise to /false/.
---
--- Some symbols have a special meaning for OpenAL:
---
--- [@devices@] Has the form @(/devspec/...)@, where /devspec/ is either a
--- symbol\/string specifying a device or @(/device/ /device-param/...)@,
--- specifying a device with additional parameters. These optional device
--- parameters are stored in a variable @device-params@, but are currently
--- unused. The first device which can successfully opened is used.
---
--- [@direction@] Type string or symbol: @\"read\"@ specifies that the device
--- should be an input device, everything else means output device (default).
---
--- [@sampling-rate@] Type integer or float: Specifies the internal mixing
--- frequency, default is 44.1kHz.
---
--- [@speaker-num@] Type integer or float: Specifies the number of speakers,
--- which can be 1, 2 (default), or 4.
---
--- [@alsa-device@] Type string, @alsa@ backend only: Specifies both
--- @alsa-out-device@ and @alsa-in-device@, default @\"plughw:0,0\"@.
--- 
--- [@alsa-out-device@] Type string, @alsa@ backend only: Specifies the ALSA
--- output device, defaults to the value of @alsa-device@.
---
--- [@alsa-in-device@] Type string, @alsa@ backend only: Specifies the ALSA
--- input device, defaults to the value of @alsa-device@.
---
--- [@native-in-device@] Type string, @native@ backend on IRIX only.
---
--- [@native-out-device@] Type string, @native@ backend on IRIX only.
---
--- [@native-rear-out-device@] Type string, @native@ backend on IRIX only.
---
--- [@native-use-select@] Type boolean, @native@ backend on Linux only: If @\#t@,
--- wait up to 0.8sec for the device to become ready for writing. If @\#f@, just
--- try to write and hope it won\'t hang forever. The latter might be necessary
--- for some drivers which don\'t implement @select()@ , like some Aureal
--- drivers.
---
--- [@lin-dsp-path@] Type string, @native@ backend on Linux only: Path to DSP
--- device for writing, tried before @\/dev\/sound\/dsp@ and @\/dev\/sound@ if
--- set.
---
--- [@lin-dsp-read-path@] Type string, @native@ backend on Linux only: Path to
--- DSP device for reading, tried before @\/dev\/sound\/dsp@ and @\/dev\/sound@
--- if set. Defaults to the value of @lin-dsp-path@.
---
--- [@native-backend-debug@] Type boolean, @native@ backend on Darwin only: If
--- set to @\#f@, be a bit verbose on stderr about what\'s going on in the
--- backend.
---
--- [@source-rolloff-factor@] Type integer or float: Value of the initial rolloff
--- factor for sources, default is @1.0@.
---
--- [@listener-position@] List of 3 integers or floats: Value of the initial
--- listener position, default is @(0 0 0)@.
---
--- [@listener-velocity@] List of 3 integers or floats: Value of the initial
--- listener velocity, default is @(0 0 0)@.
---
--- [@listener-orientation@] List of 6 integers or floats: Value of the initial
--- listener orientation (at\/up), default is @(0 0 -1 0 1 0)@.
---
--- The string given to 'openDevice' has to be of the form @\'((/symbol/
--- /expression/) ...)@, which means basically a sequence of @define@
--- expressions. Example:
---
--- @
--- \"\'((sampling-rate 8000) (native-backend-debug \#f))\"
--- @
---
--- /Note:/ The information above has been reverse-engineered from the OpenAL SI
--- and could be inaccurate. Any corrections and\/or additions are highly
--- welcome.
-
-openDevice :: Maybe String -> IO (Maybe Device)
-openDevice maybeDeviceSpec =
-   fmap unmarshalDevice $
-      maybe (alcOpenDevice nullPtr)   -- use preferred device
-            (flip withALCString alcOpenDevice)
-            maybeDeviceSpec
-
-foreign import ccall unsafe "alcOpenDevice"
-   alcOpenDevice :: Ptr ALCchar -> IO ALCdevice
-
---------------------------------------------------------------------------------
-
--- | Contains 'Just' the specifier string for the default device or 'Nothing' if
--- there is no sound support at all.
-
-defaultDeviceSpecifier :: GettableStateVar (Maybe String)
-defaultDeviceSpecifier = makeGettableStateVar $
-   getStringRaw Nothing DefaultDeviceSpecifier >>= maybePeek peekALCString
-
---------------------------------------------------------------------------------
-
--- | Contains the specifier string for the given device.
-
-deviceSpecifier :: Device -> GettableStateVar String
-deviceSpecifier device = makeGettableStateVar $
-   getString (Just device) DeviceSpecifier
-
---------------------------------------------------------------------------------
-
--- | Contains a list of specifiers for all available devices.
-
-allDeviceSpecifiers :: GettableStateVar [String]
-allDeviceSpecifiers = makeGettableStateVar $ do
-   enumExtPresent <- get (alcIsExtensionPresent Nothing "ALC_ENUMERATION_EXT")
-   if enumExtPresent
-      then getStringRaw Nothing DeviceSpecifier >>= peekALCStrings
-      else get defaultDeviceSpecifier >>= (return . maybe [] (\s -> [s]))
diff --git a/Sound/OpenAL/ALC/Errors.hs b/Sound/OpenAL/ALC/Errors.hs
deleted file mode 100644
--- a/Sound/OpenAL/ALC/Errors.hs
+++ /dev/null
@@ -1,94 +0,0 @@
-{-# LANGUAGE ForeignFunctionInterface #-}
---------------------------------------------------------------------------------
--- |
--- Module      :  Sound.OpenAL.ALC.Errors
--- Copyright   :  (c) Sven Panne 2003-2013
--- License     :  BSD3
--- 
--- Maintainer  :  Sven Panne <svenpanne@gmail.com>
--- Stability   :  stable
--- Portability :  portable
---
--- This module corresponds to section 6.3.6 (Query for Error Conditions) of the
--- OpenAL Specification and Reference (version 1.1).
---
---------------------------------------------------------------------------------
-
-module Sound.OpenAL.ALC.Errors (
-   ALCError(..), ALCErrorCategory(..), alcErrors
-) where
-
-import Foreign.C.Types
-import Graphics.Rendering.OpenGL.GL.StateVar
-import Sound.OpenAL.ALC.BasicTypes ( ALCenum )
-import Sound.OpenAL.ALC.Device ( Device )
-import Sound.OpenAL.ALC.QueryUtils ( StringQuery(..), getString )
-import Sound.OpenAL.Constants (
-   alc_NO_ERROR, alc_INVALID_DEVICE, alc_INVALID_CONTEXT, alc_INVALID_ENUM,
-   alc_INVALID_VALUE, alc_OUT_OF_MEMORY, alc_INVALID_OPERATION )
-import Sound.OpenAL.Config ( ALCdevice(..), marshalDevice )
-
---------------------------------------------------------------------------------
-
--- | ALC errors consist of a general error category and a description of what
--- went wrong.
-
-data ALCError = ALCError ALCErrorCategory String
-   deriving ( Eq, Ord, Show )
-
---------------------------------------------------------------------------------
-
--- | General ALC error categories.
-
-data ALCErrorCategory =
-     ALCInvalidEnum
-   | ALCInvalidValue
-   | ALCInvalidOperation
-   | ALCInvalidDevice
-   | ALCInvalidContext
-   | ALCOutOfMemory
-   deriving ( Eq, Ord, Show )
-
-unmarshalALCErrorCategory :: ALCenum -> ALCErrorCategory
-unmarshalALCErrorCategory x
-   | x == alc_INVALID_ENUM = ALCInvalidEnum
-   | x == alc_INVALID_VALUE = ALCInvalidValue
-   | x == alc_INVALID_OPERATION = ALCInvalidOperation
-   | x == alc_INVALID_DEVICE = ALCInvalidDevice
-   | x == alc_INVALID_CONTEXT = ALCInvalidContext
-   | x == alc_OUT_OF_MEMORY = ALCOutOfMemory
-   | otherwise = error ("unmarshalALCErrorCategory: illegal value " ++ show x)
-
---------------------------------------------------------------------------------
-
--- | OpenAL detects only a subset of those conditions that could be considered
--- errors. This is because in many cases error checking would adversely impact
--- the performance of an error-free program. The state variable 'alcErrors' is
--- used to obtain error information. When an error is detected by ALC, a flag is
--- set and the error code is recorded. Further errors, if they occur, do not
--- affect this recorded code. When 'alcErrors' is read, the error for the given
--- device is returned and the flag is cleared, so that a further error will
--- again record its code. If reading 'alcErrors' returns @\[\]@ then there has
--- been no detectable error since the last time 'alcErrors' (or since the ALC
--- was initialized).
---
--- When an error flag is set, results of ALC operations are undefined only if
--- 'ALCOutOfMemory' has occurred. In other cases, the command generating the
--- error is ignored so that it has no effect on ALC state or output buffer
--- contents. If the error generating command returns a value, it returns zero.
--- If the generating command modifies values through a pointer argument, no
--- change is made to these values. These error semantics apply only to ALC
--- errors, not to system errors such as memory access errors.
-
-alcErrors :: Device -> GettableStateVar [ALCError]
-alcErrors device =
-   makeGettableStateVar $ do
-      c <- alcGetError (marshalDevice device)
-      if c == alc_NO_ERROR
-         then return []
-         else do
-            s <- getString (Just device) (ALCErrorCategory c)
-            return [ ALCError (unmarshalALCErrorCategory c) s ]
-
-foreign import ccall unsafe "alcGetError"
-   alcGetError :: ALCdevice -> IO ALCenum
diff --git a/Sound/OpenAL/ALC/Extensions.hs b/Sound/OpenAL/ALC/Extensions.hs
deleted file mode 100644
--- a/Sound/OpenAL/ALC/Extensions.hs
+++ /dev/null
@@ -1,87 +0,0 @@
-{-# LANGUAGE ForeignFunctionInterface #-}
---------------------------------------------------------------------------------
--- |
--- Module      :  Sound.OpenAL.ALC.Extensions
--- Copyright   :  (c) Sven Panne 2003-2013
--- License     :  BSD3
--- 
--- Maintainer  :  Sven Panne <svenpanne@gmail.com>
--- Stability   :  stable
--- Portability :  portable
---
--- This module corresponds to the extension handling parts of section 6.3
--- (ALC Queries) of the OpenAL Specification and Reference (version 1.1).
---
---------------------------------------------------------------------------------
-
-module Sound.OpenAL.ALC.Extensions (
-   alcExtensions, alcIsExtensionPresent, alcProcAddress, alcEnumValue,
-   alcVersion
-) where
-
-import Control.Monad ( liftM2 )
-import Graphics.Rendering.OpenGL.GL.StateVar
-import Foreign.C.Types
-import Foreign.Ptr ( Ptr, FunPtr )
-import Sound.OpenAL.ALC.BasicTypes ( ALCchar, ALCenum, ALCint )
-import Sound.OpenAL.ALC.Device ( Device )
-import Sound.OpenAL.ALC.QueryUtils (
-   StringQuery(..), getString, IntQuery(..), getInteger, alcIsExtensionPresent )
-import Sound.OpenAL.ALC.String ( withALCString )
-import Sound.OpenAL.Config ( ALCdevice(..), nullDevice, marshalDevice )
-
---------------------------------------------------------------------------------
-
--- | Contains a list of available context extensions.
-
-alcExtensions :: Device -> GettableStateVar [String]
-alcExtensions device = makeGettableStateVar $
-   fmap words $ getString (Just device) Extensions
-
---------------------------------------------------------------------------------
-
--- | The application is expected to verify the applicability of an extension or
--- core function entry point before requesting it by name, by use of
--- 'alcIsExtensionPresent'. Extension entry points can be retrieved using
--- 'alcProcAddress'. Entry points can be device specific, but are not context
--- specific. Using 'Nothing' as the device does not guarantee that the entry
--- point is returned, even if available for one of the available devices.
-
-alcProcAddress :: Maybe Device -> String -> GettableStateVar (FunPtr a)
-alcProcAddress maybeDevice funcName =
-   makeGettableStateVar .
-      withALCString funcName .
-         alcGetProcAddress . marshalDevice . maybe nullDevice id $ maybeDevice
-
-foreign import ccall unsafe "alcGetProcAddress"
-   alcGetProcAddress :: ALCdevice -> Ptr ALCchar -> IO (FunPtr a)
-
---------------------------------------------------------------------------------
-
--- | Enumeration\/token values are device independent, but tokens defined for
--- extensions might not be present for a given device. Using 'Nothing' as the
--- device is legal, but only the tokens defined by the AL core are
--- guaranteed. Availability of extension tokens depends on the ALC extension.
-
-alcEnumValue :: Maybe Device -> String -> GettableStateVar ALCenum
-alcEnumValue maybeDevice enumName =
-   makeGettableStateVar .
-      withALCString enumName .
-         alcGetEnumValue . marshalDevice . maybe nullDevice id $ maybeDevice
-
-foreign import ccall unsafe "alcGetEnumValue"
-   alcGetEnumValue :: ALCdevice -> Ptr ALCchar -> IO ALCenum
-
---------------------------------------------------------------------------------
-
--- | Contains the \"/major/./minor/\" specification revision for this implementation.
-
-alcVersion :: GettableStateVar String
-alcVersion =
-   makeGettableStateVar $
-      liftM2 makeVersionString
-             (getInteger Nothing MajorVersion)
-             (getInteger Nothing MinorVersion)
-
-makeVersionString :: ALCint -> ALCint -> String
-makeVersionString major minor = show major ++ "." ++ show minor
diff --git a/Sound/OpenAL/ALC/QueryUtils.hs b/Sound/OpenAL/ALC/QueryUtils.hs
deleted file mode 100644
--- a/Sound/OpenAL/ALC/QueryUtils.hs
+++ /dev/null
@@ -1,123 +0,0 @@
-{-# LANGUAGE ForeignFunctionInterface #-}
-{-# OPTIONS_HADDOCK hide #-}
---------------------------------------------------------------------------------
--- |
--- Module      :  Sound.OpenAL.ALC.QueryUtils
--- Copyright   :  (c) Sven Panne 2003-2013
--- License     :  BSD3
--- 
--- Maintainer  :  Sven Panne <svenpanne@gmail.com>
--- Stability   :  stable
--- Portability :  portable
---
---------------------------------------------------------------------------------
-
-module Sound.OpenAL.ALC.QueryUtils (
-   StringQuery(..), getString, getStringRaw,
-   IntQuery(..), marshalIntQuery, getInteger, getIntegerv,
-   alcIsExtensionPresent
-) where
-
-import Control.Monad ( when )
-import Graphics.Rendering.OpenGL.GL.StateVar
-import Foreign.C.Types
-import Foreign.Marshal.Array ( withArray, peekArray )
-import Foreign.Ptr ( Ptr )
-import Sound.OpenAL.ALC.ALCboolean ( unmarshalALCboolean )
-import Sound.OpenAL.ALC.BasicTypes (
-   ALCboolean, ALCchar, ALCint, ALCenum, ALCsizei )
-import Sound.OpenAL.ALC.String ( withALCString, peekALCString )
-import Sound.OpenAL.Config ( Device, ALCdevice(..), nullDevice, marshalDevice )
-import Sound.OpenAL.Constants (
-   alc_DEFAULT_DEVICE_SPECIFIER, alc_DEVICE_SPECIFIER, alc_EXTENSIONS,
-   alc_CAPTURE_DEFAULT_DEVICE_SPECIFIER, alc_CAPTURE_DEVICE_SPECIFIER,
-   alc_ATTRIBUTES_SIZE, alc_ALL_ATTRIBUTES, alc_MAJOR_VERSION,
-   alc_MINOR_VERSION, alc_CAPTURE_SAMPLES )
-
---------------------------------------------------------------------------------
-
-data StringQuery =
-     DefaultDeviceSpecifier
-   | DeviceSpecifier
-   | Extensions
-   | CaptureDefaultDeviceSpecifier
-   | CaptureDeviceSpecifier
-   | ALCErrorCategory ALCenum
-
-marshalStringQuery :: StringQuery -> ALCenum
-marshalStringQuery x = case x of
-   DefaultDeviceSpecifier -> alc_DEFAULT_DEVICE_SPECIFIER
-   DeviceSpecifier -> alc_DEVICE_SPECIFIER
-   Extensions -> alc_EXTENSIONS
-   CaptureDefaultDeviceSpecifier -> alc_CAPTURE_DEFAULT_DEVICE_SPECIFIER
-   CaptureDeviceSpecifier -> alc_CAPTURE_DEVICE_SPECIFIER
-   ALCErrorCategory e -> e
-
---------------------------------------------------------------------------------
-
-getString :: Maybe Device -> StringQuery -> IO String
-getString device query = getStringRaw device query >>= peekALCString
-
-getStringRaw :: Maybe Device -> StringQuery -> IO (Ptr ALCchar)
-getStringRaw maybeDevice =
-   alcGetString (marshalMaybeDevice maybeDevice) . marshalStringQuery
-
-marshalMaybeDevice :: Maybe Device -> ALCdevice
-marshalMaybeDevice = marshalDevice . maybe nullDevice id
-
-foreign import ccall unsafe "alcGetString"
-   alcGetString :: ALCdevice -> ALCenum -> IO (Ptr ALCchar)
-
---------------------------------------------------------------------------------
-
-data IntQuery =
-     AttributesSize
-   | AllAttributes
-   | MajorVersion
-   | MinorVersion
-   | CaptureSamples
-
-marshalIntQuery :: IntQuery -> ALCenum
-marshalIntQuery x = case x of
-   AttributesSize -> alc_ATTRIBUTES_SIZE
-   AllAttributes -> alc_ALL_ATTRIBUTES
-   MajorVersion -> alc_MAJOR_VERSION
-   MinorVersion -> alc_MINOR_VERSION
-   CaptureSamples -> alc_CAPTURE_SAMPLES
-
---------------------------------------------------------------------------------
-
-getInteger :: Maybe Device -> IntQuery -> IO ALCint
-getInteger maybeDevice query = fmap head $ getIntegerv maybeDevice query 1
-
--- We are extremely careful below to avoid segfaults in case that there is no
--- current context, an invalid device, etc.
-getIntegerv :: Maybe Device -> IntQuery -> ALCsizei -> IO [ALCint]
-getIntegerv maybeDevice query numALCints =
-   let n = fromIntegral numALCints
-   in withArray (replicate n 0) $ \buf -> do
-         when (numALCints > 0) $
-            alcGetIntegerv (marshalMaybeDevice maybeDevice)
-                           (marshalIntQuery query) numALCints buf
-         peekArray n buf
-
-foreign import ccall unsafe "alcGetIntegerv"
-   alcGetIntegerv :: ALCdevice -> ALCenum -> ALCsizei -> Ptr ALCint -> IO ()
-
---------------------------------------------------------------------------------
-
--- | To verify that a given extension is available for the current context and
--- the device it is associated with, use 'alcIsExtensionPresent'. For invalid
--- and unsupported string tokens it contains 'False'. Using 'Nothing' as the
--- device is acceptable. The extension name is not case sensitive: The
--- implementation will convert the name to all upper-case internally (and will
--- express extension names in upper-case).
-
-alcIsExtensionPresent :: Maybe Device -> String -> GettableStateVar Bool
-alcIsExtensionPresent maybeDevice extensionName = makeGettableStateVar $
-   fmap unmarshalALCboolean $
-      withALCString extensionName $
-         alcIsExtensionPresent_ (marshalMaybeDevice maybeDevice)
-
-foreign import ccall unsafe "alcIsExtensionPresent"
-   alcIsExtensionPresent_ :: ALCdevice -> Ptr ALCchar -> IO ALCboolean
diff --git a/Sound/OpenAL/ALC/String.hs b/Sound/OpenAL/ALC/String.hs
deleted file mode 100644
--- a/Sound/OpenAL/ALC/String.hs
+++ /dev/null
@@ -1,42 +0,0 @@
-{-# OPTIONS_HADDOCK hide #-}
---------------------------------------------------------------------------------
--- |
--- Module      :  Sound.OpenAL.ALC.String
--- Copyright   :  (c) Sven Panne 2003-2013
--- License     :  BSD3
--- 
--- Maintainer  :  Sven Panne <svenpanne@gmail.com>
--- Stability   :  stable
--- Portability :  portable
---
---------------------------------------------------------------------------------
-
-module Sound.OpenAL.ALC.String (
-   withALCString, peekALCString, peekALCStrings
-) where
-
-import Foreign.C.String ( withCString, peekCString )
-import Foreign.Marshal.Array ( lengthArray0 )
-import Foreign.Ptr ( Ptr, castPtr, plusPtr )
-import Sound.OpenAL.ALC.BasicTypes ( ALCchar )
-
---------------------------------------------------------------------------------
-
--- AL uses "Ptr ALCchar" instead of "CString" for strings, so some wrappers
--- are quite handy.
-
-withALCString :: String -> (Ptr ALCchar -> IO a) -> IO a
-withALCString str action = withCString str (action . castPtr)
-
-peekALCString :: Ptr ALCchar -> IO String
-peekALCString = peekCString . castPtr
-
-peekALCStrings :: Ptr ALCchar -> IO [String]
-peekALCStrings ptr = loop ptr []
-   where loop p strs = do
-            str <- peekALCString p
-            if str == ""
-               then return (reverse strs)
-               else do
-                  len <- lengthArray0 0 p
-                  loop (p `plusPtr` (len + 1)) (str : strs)
diff --git a/Sound/OpenAL/Config.hs b/Sound/OpenAL/Config.hs
deleted file mode 100644
--- a/Sound/OpenAL/Config.hs
+++ /dev/null
@@ -1,192 +0,0 @@
-{-# LANGUAGE ForeignFunctionInterface #-}
-{-# OPTIONS_HADDOCK hide #-}
---------------------------------------------------------------------------------
--- |
--- Module      :  Sound.OpenAL.Config
--- Copyright   :  (c) Sven Panne 2003-2013
--- License     :  BSD3
--- 
--- Maintainer  :  Sven Panne <svenpanne@gmail.com>
--- Stability   :  stable
--- Portability :  portable
---
--- This purely internal module defines the platform-specific stuff which has
--- been figured out by configure.
---
---------------------------------------------------------------------------------
-
-module Sound.OpenAL.Config (
-   -- AL types
-   ALboolean, ALchar, ALbyte, ALubyte, ALshort, ALushort, ALint, ALuint,
-   ALsizei, ALenum, ALfloat, ALdouble,
-
-   -- ALC types
-   ALCboolean, ALCchar, ALCbyte, ALCubyte, ALCshort, ALCushort, ALCint, ALCuint,
-   ALCsizei, ALCenum, ALCfloat, ALCdouble,
-
-   -- Device stuff
-   ALCdevice(ALCdevice), Device, nullDevice, marshalDevice, unmarshalDevice, closeDevice,
-
-   -- Context stuff
-   ALCcontext(..), Context, nullContext, marshalContext, unmarshalContext,
-   alcProcessContext, alcMakeContextCurrent, alcDestroyContext
-) where
-
-import Foreign.C.Types
-import Foreign.Ptr ( Ptr, nullPtr )
-
---------------------------------------------------------------------------------
--- AL types
-
--- | 8-bit boolean
-type ALboolean = CChar
-
--- | Character
-type ALchar = CChar
-
--- | Signed 8-bit 2\'s complement integer
-type ALbyte = CSChar
-
--- | Unsigned 8-bit integer
-type ALubyte = CUChar
-
--- | Signed 16-bit 2\'s complement integer
-type ALshort = CShort
-
--- | Unsigned 16-bit integer
-type ALushort = CUShort
-
--- | Signed 32-bit 2\'s complement integer
-type ALint = CInt
-
--- | Unsigned 32-bit integer
-type ALuint = CUInt
-
--- | Non-negatitve 32-bit binary integer size
-type ALsizei = CInt
-
--- | Enumerated 32-bit value
-type ALenum = CInt
-
--- | 32-bit IEEE754 floating-point
-type ALfloat = CFloat
-
--- | 64-bit IEEE754 floating-point
-type ALdouble = CDouble
-
---------------------------------------------------------------------------------
--- ALC types
-
--- | 8-bit boolean
-type ALCboolean = CChar
-
--- | Character
-type ALCchar = CChar
-
--- | Signed 8-bit 2\'s complement integer
-type ALCbyte = CSChar
-
--- | Unsigned 8-bit integer
-type ALCubyte = CUChar
-
--- | Signed 16-bit 2\'s complement integer
-type ALCshort = CShort
-
--- | Unsigned 16-bit integer
-type ALCushort = CUShort
-
--- | Signed 32-bit 2\'s complement integer
-type ALCint = CInt
-
--- | Unsigned 32-bit integer
-type ALCuint = CUInt
-
--- | Non-negatitve 32-bit binary integer size
-type ALCsizei = CInt
-
--- | Enumerated 32-bit value
-type ALCenum = CInt
-
--- | 32-bit IEEE754 floating-point
-type ALCfloat = CFloat
-
--- | 64-bit IEEE754 floating-point
-type ALCdouble = CDouble
-
---------------------------------------------------------------------------------
--- In OpenAL 1.1, alcCloseDevice() returns an ALCboolean, before it was void.
--- To break a dependency cycle, we have to define the Device type here, too.
-
--- | The abstract device type.
-
-newtype Device = Device ALCdevice
-   deriving ( Eq, Ord, Show )
-
-newtype ALCdevice = ALCdevice (Ptr ALCdevice)
-   deriving ( Eq, Ord, Show )
-
-nullDevice :: Device
-nullDevice = Device (ALCdevice nullPtr)
-
-marshalDevice :: Device -> ALCdevice
-marshalDevice (Device device) = device
-
-unmarshalDevice :: ALCdevice -> Maybe Device
-unmarshalDevice device =
-   if device == marshalDevice nullDevice then Nothing else Just (Device device)
-
--- | 'closeDevice' allows the application (i.e. the client program) to
--- disconnect from a device (i.e. the server). It returns 'True' for success and
--- 'False' for failure. Once closed, the 'Device' is invalid.
---
--- /Note:/ Older OpenAL implementations will always report a success!
-
-closeDevice :: Device -> IO Bool
--- inlined unmarshalALCboolean here to break dependency cycle
-closeDevice = fmap (/= 0) . alcCloseDevice . marshalDevice
-
-foreign import ccall unsafe "alcCloseDevice"
-   alcCloseDevice :: ALCdevice -> IO ALCboolean
-
---------------------------------------------------------------------------------
--- In OpenAL 1.1, alcProcessContext() returns void for all platforms, before it
--- returned ALCcontext* on Linux. To break a dependency cycle, we have to define
--- the Context type here, too.
-
--- | The abstract context type.
-
-data Context = Context ALCcontext
-   deriving ( Eq, Ord, Show )
-
-newtype ALCcontext = ALCcontext (Ptr ALCcontext)
-   deriving ( Eq, Ord, Show )
-
-nullContext :: Context
-nullContext = Context (ALCcontext nullPtr)
-
-marshalContext :: Context -> ALCcontext
-marshalContext (Context context) = context
-
-unmarshalContext :: ALCcontext -> Maybe Context
-unmarshalContext context =
-   if context == marshalContext nullContext then Nothing else Just (Context context)
-
---------------------------------------------------------------------------------
--- In ancient times, alcProcessContext returned ALCcontext.
-
-foreign import ccall unsafe "alcProcessContext"
-   alcProcessContext :: ALCcontext -> IO ()
-
---------------------------------------------------------------------------------
--- In OpenAL 1.1, alcMakeContextCurrent() returns void, before it was ALCenum on
--- Linux and ALCboolean on other platforms.
-
-foreign import ccall unsafe "alcMakeContextCurrent"
-   alcMakeContextCurrent :: ALCcontext -> IO ALCboolean
-
---------------------------------------------------------------------------------
--- In OpenAL 1.1, alcDestroyContext() returns void, before it returned ALCenum
--- on Linux.
-
-foreign import ccall unsafe "alcDestroyContext"
-   alcDestroyContext :: ALCcontext -> IO ()
diff --git a/Sound/OpenAL/Constants.hs b/Sound/OpenAL/Constants.hs
deleted file mode 100644
--- a/Sound/OpenAL/Constants.hs
+++ /dev/null
@@ -1,162 +0,0 @@
-{-# OPTIONS_HADDOCK hide #-}
---------------------------------------------------------------------------------
--- |
--- Module      :  Sound.OpenAL.Constants
--- Copyright   :  (c) Sven Panne 2003-2013
--- License     :  BSD3
--- 
--- Maintainer  :  Sven Panne <svenpanne@gmail.com>
--- Stability   :  stable
--- Portability :  portable
---
--- This purely internal module defines all AL\/ALC constants, which have been
--- figured out by configure. In contrast to OpenGL and GLUT, these constants
--- varied on different platforms in the past and have evolved quite a bit.
---
---------------------------------------------------------------------------------
-
-module Sound.OpenAL.Constants where
-
-import Sound.OpenAL.Config (
-   ALboolean, ALint, ALenum, ALCboolean, ALCint, ALCenum )
-
---------------------------------------------------------------------------------
-
-al_FALSE, al_TRUE :: ALboolean
-al_FALSE                            = 0x0000
-al_TRUE                             = 0x0001
-
-al_NO_ERROR, al_INVALID_NAME, al_INVALID_ENUM, al_INVALID_VALUE,
-   al_INVALID_OPERATION, al_OUT_OF_MEMORY :: ALenum
-al_NO_ERROR                         = 0x0000
-al_INVALID_NAME                     = 0xA001
-al_INVALID_ENUM                     = 0xA002
-al_INVALID_VALUE                    = 0xA003
-al_INVALID_OPERATION                = 0xA004
-al_OUT_OF_MEMORY                    = 0xA005
-
---------------------------------------------------------------------------------
-
-al_DISTANCE_MODEL, al_DOPPLER_FACTOR, al_SPEED_OF_SOUND :: ALenum
-al_DISTANCE_MODEL                   = 0xD000
-al_DOPPLER_FACTOR                   = 0xC000
-al_SPEED_OF_SOUND                   = 0xC003
-
-al_VERSION, al_RENDERER, al_VENDOR, al_EXTENSIONS :: ALenum
-al_VERSION                          = 0xB002
-al_RENDERER                         = 0xB003
-al_VENDOR                           = 0xB001
-al_EXTENSIONS                       = 0xB004
-
-al_NONE, al_INVERSE_DISTANCE, al_INVERSE_DISTANCE_CLAMPED, al_LINEAR_DISTANCE,
-   al_LINEAR_DISTANCE_CLAMPED, al_EXPONENT_DISTANCE,
-   al_EXPONENT_DISTANCE_CLAMPED :: ALenum
-al_NONE                             = 0x0000
-al_INVERSE_DISTANCE                 = 0xD001
-al_INVERSE_DISTANCE_CLAMPED         = 0xD002
-al_LINEAR_DISTANCE                  = 0xD003
-al_LINEAR_DISTANCE_CLAMPED          = 0xD004
-al_EXPONENT_DISTANCE                = 0xD005
-al_EXPONENT_DISTANCE_CLAMPED        = 0xD006
-
---------------------------------------------------------------------------------
-
-al_POSITION, al_VELOCITY, al_GAIN :: ALenum
-al_POSITION                         = 0x1004
-al_VELOCITY                         = 0x1006
-al_GAIN                             = 0x100A
-
-al_ORIENTATION :: ALenum
-al_ORIENTATION                      = 0x100F
-
-al_SOURCE_RELATIVE, al_SOURCE_TYPE, al_LOOPING, al_BUFFER, al_BUFFERS_QUEUED,
-   al_BUFFERS_PROCESSED, al_MIN_GAIN, al_MAX_GAIN, al_REFERENCE_DISTANCE,
-   al_ROLLOFF_FACTOR, al_MAX_DISTANCE, al_PITCH, al_DIRECTION,
-   al_CONE_INNER_ANGLE, al_CONE_OUTER_ANGLE, al_CONE_OUTER_GAIN, al_SEC_OFFSET,
-   al_SAMPLE_OFFSET, al_BYTE_OFFSET, al_SOURCE_STATE :: ALenum
-al_SOURCE_RELATIVE                  = 0x0202
-al_SOURCE_TYPE                      = 0x1027
-al_LOOPING                          = 0x1007
-al_BUFFER                           = 0x1009
-al_BUFFERS_QUEUED                   = 0x1015
-al_BUFFERS_PROCESSED                = 0x1016
-al_MIN_GAIN                         = 0x100D
-al_MAX_GAIN                         = 0x100E
-al_REFERENCE_DISTANCE               = 0x1020
-al_ROLLOFF_FACTOR                   = 0x1021
-al_MAX_DISTANCE                     = 0x1023
-al_PITCH                            = 0x1003
-al_DIRECTION                        = 0x1005
-al_CONE_INNER_ANGLE                 = 0x1001
-al_CONE_OUTER_ANGLE                 = 0x1002
-al_CONE_OUTER_GAIN                  = 0x1022
-al_SEC_OFFSET                       = 0x1024
-al_SAMPLE_OFFSET                    = 0x1025
-al_BYTE_OFFSET                      = 0x1026
-al_SOURCE_STATE                     = 0x1010
-
-al_UNDETERMINED, al_STATIC, al_STREAMING :: ALint
-al_UNDETERMINED                     = 0x1030
-al_STATIC                           = 0x1028
-al_STREAMING                        = 0x1029
-
-al_INITIAL, al_PLAYING, al_PAUSED, al_STOPPED :: ALint
-al_INITIAL                          = 0x1011
-al_PLAYING                          = 0x1012
-al_PAUSED                           = 0x1013
-al_STOPPED                          = 0x1014
-
---------------------------------------------------------------------------------
-
-al_FREQUENCY, al_SIZE, al_BITS, al_CHANNELS :: ALenum
-al_FREQUENCY                        = 0x2001
-al_SIZE                             = 0x2004
-al_BITS                             = 0x2002
-al_CHANNELS                         = 0x2003
-
-al_FORMAT_MONO8, al_FORMAT_MONO16, al_FORMAT_STEREO8,
-   al_FORMAT_STEREO16 :: ALenum
-al_FORMAT_MONO8                     = 0x1100
-al_FORMAT_MONO16                    = 0x1101
-al_FORMAT_STEREO8                   = 0x1102
-al_FORMAT_STEREO16                  = 0x1103
-
---------------------------------------------------------------------------------
-
-alc_FALSE, alc_TRUE :: ALCboolean
-alc_FALSE                           = 0x0000
-alc_TRUE                            = 0x0001
-
-alc_FREQUENCY, alc_REFRESH, alc_SYNC, alc_MONO_SOURCES,
-   alc_STEREO_SOURCES :: ALCint
-alc_FREQUENCY                       = 0x1007
-alc_REFRESH                         = 0x1008
-alc_SYNC                            = 0x1009
-alc_MONO_SOURCES                    = 0x1010
-alc_STEREO_SOURCES                  = 0x1011
-
-alc_NO_ERROR, alc_INVALID_DEVICE, alc_INVALID_CONTEXT, alc_INVALID_ENUM,
-   alc_INVALID_VALUE, alc_INVALID_OPERATION, alc_OUT_OF_MEMORY :: ALCenum
-alc_NO_ERROR                        = 0x0000
-alc_INVALID_DEVICE                  = 0xA001
-alc_INVALID_CONTEXT                 = 0xA002
-alc_INVALID_ENUM                    = 0xA003
-alc_INVALID_VALUE                   = 0xA004
-alc_INVALID_OPERATION               = 0xA006
-alc_OUT_OF_MEMORY                   = 0xA005
-
-alc_DEFAULT_DEVICE_SPECIFIER, alc_DEVICE_SPECIFIER, alc_EXTENSIONS,
-   alc_CAPTURE_DEFAULT_DEVICE_SPECIFIER, alc_CAPTURE_DEVICE_SPECIFIER :: ALCenum
-alc_DEFAULT_DEVICE_SPECIFIER        = 0x1004
-alc_DEVICE_SPECIFIER                = 0x1005
-alc_EXTENSIONS                      = 0x1006
-alc_CAPTURE_DEFAULT_DEVICE_SPECIFIER= 0x0311
-alc_CAPTURE_DEVICE_SPECIFIER        = 0x0310
-
-alc_ATTRIBUTES_SIZE, alc_ALL_ATTRIBUTES, alc_MAJOR_VERSION, alc_MINOR_VERSION,
-   alc_CAPTURE_SAMPLES :: ALCenum
-alc_ATTRIBUTES_SIZE                 = 0x1002
-alc_ALL_ATTRIBUTES                  = 0x1003
-alc_MAJOR_VERSION                   = 0x1000
-alc_MINOR_VERSION                   = 0x1001
-alc_CAPTURE_SAMPLES                 = 0x0312
diff --git a/src/Sound/OpenAL.hs b/src/Sound/OpenAL.hs
new file mode 100644
--- /dev/null
+++ b/src/Sound/OpenAL.hs
@@ -0,0 +1,181 @@
+--------------------------------------------------------------------------------
+-- |
+-- Module      :  Sound.OpenAL
+-- Copyright   :  (c) Sven Panne 2003-2013
+-- License     :  BSD3
+--
+-- Maintainer  :  Sven Panne <svenpanne@gmail.com>
+-- Stability   :  stable
+-- Portability :  portable
+--
+-- A convenience module, combining the Haskell bindings for AL and ALC.
+--
+--------------------------------------------------------------------------------
+
+module Sound.OpenAL (
+   -- * A Brief History of OpenAL
+   -- $ABriefHistoryOfOpenAL
+
+   -- * What is the OpenAL Audio System?
+   -- $WhatIsTheOpenALAudioSystem
+
+   -- * Different Views of OpenAL
+
+   -- ** Programmer\'s View of OpenAL
+   -- $ProgrammersViewOfOpenAL
+
+   -- ** Implementor\'s View of OpenAL
+   -- $ImplementorsViewOfOpenAL
+
+   -- ** The Specification\'s View of OpenAL
+   -- $TheSpecificationsViewOfOpenAL
+
+   -- * Legal stuff
+   -- $LegalStuff
+
+     module Sound.OpenAL.AL
+   , module Sound.OpenAL.ALC
+
+   -- * Convenience Re-exports
+   , module Graphics.Rendering.OpenGL.GL.ObjectName
+   , module Graphics.Rendering.OpenGL.GL.StateVar
+   , module Graphics.Rendering.OpenGL.GL.Tensor
+) where
+
+import Sound.OpenAL.AL
+import Sound.OpenAL.ALC
+
+import Graphics.Rendering.OpenGL.GL.ObjectName
+import Graphics.Rendering.OpenGL.GL.StateVar
+import Graphics.Rendering.OpenGL.GL.Tensor ( Vector3(..), Vertex3(..) )
+
+--------------------------------------------------------------------------------
+-- $ABriefHistoryOfOpenAL
+-- The first discussions about implementing OpenAL as an audio API complimentary
+-- to OpenGL started around 1998. There were a few aborted attempts at creating
+-- the headers and a specification, but by late 1999 Loki Entertainment Software
+-- was in need for an API of exactly this type and pursued both a specification
+-- and a Linux implementation. At around that time, Loki started talking with
+-- Creative Labs about standardizing the API and expanding platform support. The
+-- OpenAL 1.0 specification was released in early 2000 and compliant OpenAL
+-- libraries were released in the same year for Linux, MacOS 8\/9, Windows, and
+-- BeOS. Loki Entertainment also shipped several games using OpenAL in 2000:
+-- Heavy Gear 2 and Heretic 2 (both under Linux). In 2001, Creative Labs
+-- released the first hardware-accelerated OpenAL libraries. The libraries
+-- supported the SoundBlaster Live on MacOS 8\/9 and Windows.
+--
+-- Since 2001, there has been continuous improvement in OpenAL. Some platforms
+-- are less relevant than in 2000 (BeOS and MacOS 8\/9 for instance), but more
+-- platforms have been added as well (BSD, Solaris, IRIX, Mac OS X, and the
+-- popular console gaming platforms). Hardware support is enabled for many
+-- Creative and NVIDIA audio devices under Windows as well.
+--
+-- In terms of product support, OpenAL has been used in a large number of titles
+-- over the years, on many platforms (for a list of many of the titles, see
+-- <http://www.openal.org/titles.html>).
+
+--------------------------------------------------------------------------------
+-- $WhatIsTheOpenALAudioSystem
+-- OpenAL (for /Open Audio Library/) is a software interface to audio hardware.
+-- The interface consists of a number of functions that allow a programmer to
+-- specify the objects and operations in producing high-quality audio output,
+-- specifically multichannel output of 3D arrangements of sound sources around a
+-- listener.
+--
+-- The OpenAL API is designed to be cross-platform and easy to use. It resembles
+-- the OpenGL API in coding style and conventions. OpenAL uses a syntax
+-- resembling that of OpenGL where applicable. For more information on OpenGL,
+-- see <http://www.opengl.org/> and the "Graphics.Rendering.OpenGL" module.
+--
+-- OpenAL is foremost a means to generate audio in a simulated three-dimensional
+-- space.  Consequently, legacy audio concepts such as panning and left\/right
+-- channels are not directly supported. OpenAL does include extensions
+-- compatible with the IA-SIG 3D Level 1 and Level 2 rendering guidelines to
+-- handle sound-source directivity and distancerelated attenuation and Doppler
+-- effects, as well as environmental effects such as reflection, obstruction,
+-- transmission, reverberation. For more information on IA-SIG 3D, see
+-- <http://www.iasig.org/wg/closed/3dwg/3dwg.shtml>.
+--
+-- Like OpenGL, the OpenAL core API has no notion of an explicit rendering
+-- context, and operates on an implied current OpenAL Context. Unlike the OpenGL
+-- specification, the OpenAL specification includes both the core API (the
+-- actual OpenAL API, see "Sound.OpenAL.AL") and the operating system bindings
+-- of the ALC API (the /Audio Library Context/, see "Sound.OpenAL.ALC"). Unlike
+-- OpenGL\'s GLX, WGL and other OS-specific bindings, the ALC API is portable
+-- across platforms as well.
+
+--------------------------------------------------------------------------------
+-- $ProgrammersViewOfOpenAL
+-- To the programmer, OpenAL is a set of commands that allow the specification
+-- of sound sources and a listener in three dimensions, combined with commands
+-- that control how these sound sources are rendered into the output buffer. The
+-- effect of OpenAL commands is not guaranteed to be immediate, as there are
+-- latencies depending on the implementation, but ideally such latency should
+-- not be noticeable to the user.
+--
+-- A typical program that uses OpenAL begins with calls to open a sound device
+-- which is used to process output and play it on attached hardware (speakers or
+-- headphones). Then, calls are made to allocate an AL context and associate it
+-- with the device. Once an AL context is allocated, the programmer is free to
+-- issue AL commands. Some calls are used to render sources (point and
+-- directional sources, looping or not), while others affect the rendering of
+-- these sources including how they are attenuated by distance and relative
+-- orientation.
+
+--------------------------------------------------------------------------------
+-- $ImplementorsViewOfOpenAL
+-- To the implementor, OpenAL is a set of commands that affect the operation of
+-- CPU and sound hardware. If the hardware consists only of an addressable
+-- output buffer, then OpenAL must be implemented almost entirely on the host
+-- CPU. In some cases audio hardware provides DSP-based and other acceleration
+-- in various degrees. The OpenAL implementor\'s task is to provide the CPU
+-- software interface while dividing the work for each AL command between the
+-- CPU and the audio hardware. This division should be tailored to the available
+-- audio hardware to obtain optimum performance in carrying out AL calls.
+--
+-- OpenAL maintains a considerable amount of state information. This state
+-- controls how the sources are rendered into the output buffer. Some of this
+-- state is directly available to the user: he or she can make calls to obtain
+-- its value. Some of it, however, is visible only by the effect it has on what
+-- is rendered. One of the main goals of the OpenAL specification is to make
+-- OpenAL state information explicit, to elucidate how it changes, and to
+-- indicate what its effects are.
+
+--------------------------------------------------------------------------------
+-- $TheSpecificationsViewOfOpenAL
+-- The OpenAL specification (see <http://www.openal.org/documentation.html>)
+-- views OpenAL as a state machine that controls a multichannel processing
+-- system to synthesize a digital stream, passing sample data through a chain of
+-- parametrized digital audio signal processing operations. This model should
+-- engender a specification that satisfies the needs of both programmers and
+-- implementors. It does not, however, necessarily provide a model for
+-- implementation. Any proper implementation must produce results conforming to
+-- those produced by the methods specified in the OpenAL specification, but
+-- there may be ways to carry out a particular computation that are more
+-- efficient than the one specified.
+
+--------------------------------------------------------------------------------
+-- $LegalStuff
+-- The documentation is more or less based upon the OpenAL 1.1 Specification and
+-- Reference, which is in turn based upon the older OpenAL Specification and
+-- Reference (1.0), published in June 2000. Both copyright notices are presented
+-- below:
+--
+-- Version 1.1: Published June 2005, Copyright (c) 2005 by authors
+--
+-- Version 1.0 Draft Edition: Published June 2000, Copyright (c) 1999-2000 by
+-- Loki Software
+--
+-- Permission is granted to make and distribute verbatim copies of this manual
+-- provided the copyright notice and this permission notice are preserved on all
+-- copies.  Permission is granted to copy and distribute translations of this
+-- manual into another language, under the above conditions for modified
+-- versions, except that this permission notice may be stated in a translation
+-- approved by the copyright owners.
+--
+-- BeOS is a trademark of PalmSource, Inc. Linux is a trademark of Linus
+-- Torvalds. Macintosh and Apple are trademarks of Apple Computer, Inc. OpenAL
+-- is a trademark of Creative Labs, Inc. OpenGL is a trademark of Silicon
+-- Graphics, Inc. UNIX is a trademark of X\/Open Group. Windows is a trademark
+-- of Microsoft Corp. X Window System is a trademark of X Consortium, Inc. All
+-- other trademarks are property of their respective owners.
diff --git a/src/Sound/OpenAL/AL.hs b/src/Sound/OpenAL/AL.hs
new file mode 100644
--- /dev/null
+++ b/src/Sound/OpenAL/AL.hs
@@ -0,0 +1,128 @@
+--------------------------------------------------------------------------------
+-- |
+-- Module      :  Sound.OpenAL.AL
+-- Copyright   :  (c) Sven Panne 2003-2013
+-- License     :  BSD3
+-- 
+-- Maintainer  :  Sven Panne <svenpanne@gmail.com>
+-- Stability   :  stable
+-- Portability :  portable
+--
+-- This module corresponds to chapters 2 (OpenAL Operation), 3 (State and State
+-- Requests), 4 (Listener and Sources) and 5 (Buffers) of the OpenAL
+-- Specification and Reference (version 1.1).
+--
+--------------------------------------------------------------------------------
+
+module Sound.OpenAL.AL (
+   -- * OpenAL Fundamentals
+   -- $OpenALFundamentals
+
+   -- * Basic AL Operation
+   -- $BasicALOperation
+
+   -- * Time and Frequency
+   -- $TimeAndFrequency
+
+   -- * Space and Distance
+   -- $SpaceAndDistance
+
+   -- * Coordinate System
+   -- $CoordinateSystem
+
+   module Sound.OpenAL.AL.BasicTypes,
+   module Sound.OpenAL.AL.Errors,
+   module Sound.OpenAL.AL.StringQueries,
+   module Sound.OpenAL.AL.Attenuation,
+   module Sound.OpenAL.AL.Doppler,
+   module Sound.OpenAL.AL.Listener,
+   module Sound.OpenAL.AL.Source,
+   module Sound.OpenAL.AL.Buffer,
+   module Sound.OpenAL.AL.Extensions
+) where
+
+import Sound.OpenAL.AL.BasicTypes
+import Sound.OpenAL.AL.Errors
+import Sound.OpenAL.AL.StringQueries
+import Sound.OpenAL.AL.Attenuation
+import Sound.OpenAL.AL.Doppler
+import Sound.OpenAL.AL.Listener
+import Sound.OpenAL.AL.Source
+import Sound.OpenAL.AL.Buffer
+import Sound.OpenAL.AL.Extensions
+
+--------------------------------------------------------------------------------
+-- $OpenALFundamentals
+-- OpenAL is concerned with rendering audio into an output buffer and collecting
+-- audio data from an input buffer. OpenAL\'s primary use is assumed to be for
+-- spatialized audio. There is no support for MIDI.
+--
+-- OpenAL has three fundamental primitives or objects: 'Buffer's, 'Source's, and
+-- a single listener (see "Sound.OpenAL.AL.Listener"). Each object can be
+-- changed independently; the setting of one object does not affect the setting
+-- of others. The application can also set modes that affect processing. Modes
+-- are set, objects specified, and other OpenAL operations performed by sending
+-- commands in the form of function or procedure calls.
+--
+-- Sources store locations, directions, and other attributes of an object in 3D
+-- space and have a buffer associated with them for playback. When the program
+-- wants to play a sound, it controls execution through a source object. Sources
+-- are processed independently from each other.
+--
+-- Buffers store compressed or uncompressed audio data. It is common to
+-- initialize a large set of buffers when the program first starts (or at
+-- non-critical times during execution, between levels in a game, for
+-- instance). Buffers are referred to by sources. Data (audio sample data) is
+-- associated with buffers.
+--
+-- There is only one listener (per audio context). The listener attributes are
+-- similar to source attributes, but are used to represent where the user is
+-- hearing the audio from. The influence of all the sources from the perspective
+-- of the listener is mixed and played for the user.
+
+--------------------------------------------------------------------------------
+-- $BasicALOperation
+-- OpenAL can be used for a variety of audio playback tasks, and is an excellent
+-- complement to OpenGL for real-time rendering, see
+-- "Graphics.Rendering.OpenGL". A programmer who is familiar with OpenGL will
+-- immediately notice the similarities between the two APIs in that they
+-- describe their 3D environments using similar methods.
+-- 
+-- For an OpenGL\/OpenAL program, most of the audio programming will be in two
+-- places in the code: initialization of the program, and the rendering loop. An
+-- OpenGL\/OpenAL program will typically contain a section where the graphics
+-- and audio systems are initialized, although it may be spread into multiple
+-- functions. For OpenAL, initialization normally consists of creating a
+-- context, creating the initial set of buffers, loading the buffers with sample
+-- data, creating sources, attaching buffers to sources, setting locations and
+-- directions for the listener and sources, and setting the initial values for
+-- state global to OpenAL.
+
+--------------------------------------------------------------------------------
+-- $TimeAndFrequency
+-- By default, OpenAL uses seconds and Hertz as units for time and frequency,
+-- respectively. A float or integral value of one for a variable that specifies
+-- quantities like duration, latency, delay, or any other parameter measured as
+-- time, specifies 1 second. For frequency, the basic unit is 1\/second, or
+-- Hertz. In other words, sample frequencies and frequency cut-offs or filter
+-- parameters specifying frequencies are expressed in units of Hertz.
+
+--------------------------------------------------------------------------------
+-- $SpaceAndDistance
+-- OpenAL does not define the units of measurement for distances. The
+-- application is free to use meters, inches, or parsecs. OpenAL provides means
+-- for simulating the natural attenuation of sound according to distance, and to
+-- exaggerate or reduce this effect.  However, the resulting effects do not
+-- depend on the distance unit used by the application to express source and
+-- listener coordinates. OpenAL calculations are scale invariant.  The
+-- specification assumes Euclidean calculation of distances, and mandates that
+-- if two sources are sorted with respect to the Euclidean metric, the distance
+-- calculation used by the implementation has to preserve that order.
+
+--------------------------------------------------------------------------------
+-- $CoordinateSystem
+-- OpenAL - like OpenGL - uses a right-handed Cartesian coordinate system (RHS),
+-- where in a frontal default view X (thumb) points right, Y (index finger)
+-- points up, and Z (middle finger) points towards the viewer\/camera. To switch
+-- from a left handed coordinate system (LHS) to a right handed coordinate
+-- systems, flip the sign on the Z coordinate.
diff --git a/src/Sound/OpenAL/AL/ALboolean.hs b/src/Sound/OpenAL/AL/ALboolean.hs
new file mode 100644
--- /dev/null
+++ b/src/Sound/OpenAL/AL/ALboolean.hs
@@ -0,0 +1,30 @@
+{-# OPTIONS_HADDOCK hide #-}
+--------------------------------------------------------------------------------
+-- |
+-- Module      :  Sound.OpenAL.AL.ALboolean
+-- Copyright   :  (c) Sven Panne 2003-2013
+-- License     :  BSD3
+-- 
+-- Maintainer  :  Sven Panne <svenpanne@gmail.com>
+-- Stability   :  stable
+-- Portability :  portable
+--
+-- This is a purely internal module for (un-)marshaling ALboolean.
+--
+--------------------------------------------------------------------------------
+
+module Sound.OpenAL.AL.ALboolean (
+   marshalALboolean, unmarshalALboolean
+) where
+
+import Sound.OpenAL.AL.BasicTypes ( ALboolean )
+import Sound.OpenAL.Constants ( al_FALSE, al_TRUE )
+
+--------------------------------------------------------------------------------
+
+marshalALboolean :: Bool -> ALboolean
+marshalALboolean False = al_FALSE
+marshalALboolean True  = al_TRUE
+
+unmarshalALboolean :: ALboolean -> Bool
+unmarshalALboolean = (/= al_FALSE)
diff --git a/src/Sound/OpenAL/AL/Attenuation.hs b/src/Sound/OpenAL/AL/Attenuation.hs
new file mode 100644
--- /dev/null
+++ b/src/Sound/OpenAL/AL/Attenuation.hs
@@ -0,0 +1,206 @@
+{-# OPTIONS_GHC -fno-warn-unused-imports #-}
+--------------------------------------------------------------------------------
+-- |
+-- Module      :  Sound.OpenAL.AL.Attenuation
+-- Copyright   :  (c) Sven Panne 2003-2013
+-- License     :  BSD3
+-- 
+-- Maintainer  :  Sven Panne <svenpanne@gmail.com>
+-- Stability   :  stable
+-- Portability :  portable
+--
+-- This module corresponds to section 3.4 (Attenuation By Distance) of the
+-- OpenAL Specification and Reference (version 1.1).
+-- 
+--------------------------------------------------------------------------------
+
+module Sound.OpenAL.AL.Attenuation (
+   -- * Introduction
+   -- $Introduction
+
+   -- * Handling the Distance Model
+   DistanceModel(..), distanceModel
+
+   -- * Evaluation of Gain\/Attenuation Related State
+   -- $EvaluationOfGainAttenuationRelatedState
+
+   -- * No Culling By Distance
+   -- $NoCullingByDistance
+) where
+
+import Foreign.C.Types
+import Foreign.Marshal.Alloc
+import Foreign.Ptr
+import Graphics.Rendering.OpenGL.GL.StateVar
+import Sound.OpenAL.AL.BasicTypes
+import Sound.OpenAL.AL.PeekPoke
+import Sound.OpenAL.AL.QueryUtils
+import Sound.OpenAL.Constants
+
+-- For Haddock only.
+import Sound.OpenAL.AL.Source
+
+--------------------------------------------------------------------------------
+-- $Introduction
+-- Samples usually use the entire dynamic range of the chosen format\/encoding,
+-- independent of their real world intensity. In other words, a jet engine and a
+-- clockwork both will have samples with full amplitude. The application will
+-- then have to adjust source gain accordingly to account for relative
+-- differences.
+-- 
+-- Source gain is then attenuated by distance. The effective attenuation of a
+-- source depends on many factors, among which distance attenuation and source
+-- and listener gain are only some of the contributing factors. Even if the
+-- source and listener gain exceed 1 (amplification beyond the guaranteed
+-- dynamic range), distance and other attenuation might ultimately limit the
+-- overall gain to a value below 1.
+
+--------------------------------------------------------------------------------
+-- $EvaluationOfGainAttenuationRelatedState
+-- While amplification\/attenuation commute (multiplication of scaling factors),
+-- clamping operations do not. The order in which various gain related
+-- operations are applied is:
+-- 
+-- 1. Distance attenuation is calculated first, including minimum
+-- ('referenceDistance') and maximum ('maxDistance') thresholds.
+-- 
+-- 2. The result is then multiplied by source gain.
+-- 
+-- 3. If the source is directional (the inner cone angle is less than the outer
+-- cone angle, see 'coneAngles'), an angle-dependent attenuation is calculated
+-- depending on 'coneOuterGain', and multiplied with the distance-dependent
+-- attenuation. The resulting attenuation factor for the given angle and
+-- distance between listener and source is multiplied with 'sourceGain'.
+-- 
+-- 4. The effective gain computed this way is compared against 'gainBounds'.
+-- 
+-- 5. The result is guaranteed to be clamped to 'gainBounds', and subsequently
+-- multiplied by listener gain which serves as an overall volume control.
+-- 
+-- The implementation is free to clamp listener gain if necessary due to
+-- hardware or implementation constraints.
+
+--------------------------------------------------------------------------------
+-- $NoCullingByDistance
+-- With the DS3D compatible inverse clamped distance model, OpenAL provides a
+-- per-source 'maxDistance' attribute that can be used to define a distance
+-- beyond which the source will not be further attenuated by distance. The DS3D
+-- distance attenuation model and its clamping of volume is also extended by a
+-- mechanism to cull (mute) sources from processing, based on distance. However,
+-- the OpenAL does not support culling a source from processing based on a
+-- distance threshold.
+-- 
+-- At this time OpenAL is not meant to support culling at all. Culling based on
+-- distance, or bounding volumes, or other criteria, is best left to the
+-- application. For example, the application might employ sophisticated
+-- techniques to determine whether sources are audible that are beyond the scope
+-- of OpenAL. In particular, rule based culling inevitably introduces acoustic
+-- artifacts. E.g. if the listener-source distance is nearly equal to the culling
+-- threshold distance, but varies above and below, there will be popping
+-- artifacts in the absence of hysteresis.
+
+--------------------------------------------------------------------------------
+
+-- | OpenAL currently supports six modes of operation with respect to distance
+-- attenuation, including one that is similar to the IASIG I3DL2 model. The
+-- application chooses one of these models (or chooses to disable
+-- distance-dependent attenuation) on a per-context basis.
+--
+-- The distance used in the formulas for the \"clamped\" modes below is clamped
+-- to be in the range between 'referenceDistance' and 'maxDistance':
+--
+-- /clamped distance/ =
+--    max('referenceDistance', min(/distance/, 'maxDistance'))
+--
+-- The linear models are not physically realistic, but do allow full attenuation
+-- of a source beyond a specified distance. The OpenAL implementation is still
+-- free to apply any range clamping as necessary.
+-- 
+-- With all the distance models, if the formula can not be evaluated then the
+-- source will not be attenuated. For example, if a linear model is being used
+-- with 'referenceDistance' equal to 'maxDistance', then the gain equation will
+-- have a divide-by-zero error in it. In this case, there is no attenuation for
+-- that source.
+
+data DistanceModel =
+     NoAttenuation
+   -- ^ Bypass all distance attenuation calculation for all sources. The
+   --   implementation is expected to optimize this situation.
+   | InverseDistance
+   -- ^ Inverse distance rolloff model, which is equivalent to the IASIG I3DL2
+   --   model with the exception that 'referenceDistance' does not imply any
+   --   clamping.
+   --
+   --   /gain/ = 'referenceDistance' \/ ('referenceDistance' +
+   --             'rolloffFactor' \* (/distance/ - 'referenceDistance'))
+   --
+   --   The 'referenceDistance' parameter used here is a per-source attribute
+   --   which is the distance at which the listener will experience gain
+   --   (unless the implementation had to clamp effective gain to the available
+   --   dynamic range). 'rolloffFactor' is per-source parameter the application
+   --   can use to increase or decrease the range of a source by decreasing or
+   --   increasing the attenuation, respectively. The default value is 1. The
+   --   implementation is free to optimize for a 'rolloffFactor' value of 0,
+   --   which indicates that the application does not wish any distance
+   --   attenuation on the respective source.
+   | InverseDistanceClamped
+   -- ^ Inverse Distance clamped model, which is essentially the inverse
+   --   distance rolloff model, extended to guarantee that for distances below
+   --   'referenceDistance', gain is clamped. This mode is equivalent to the
+   --   IASIG I3DL2 distance model.
+   | LinearDistance
+   -- ^ Linear distance rolloff model, modeling a linear dropoff in gain as
+   -- distance increases between the source and listener.
+   --
+   --   /gain/ = (1 - 'rolloffFactor' \* (/distance/ - 'referenceDistance') \/
+   --            ('maxDistance' - 'referenceDistance'))
+   | LinearDistanceClamped
+   -- ^ Linear Distance clamped model, which is the linear model, extended to
+   --   guarantee that for distances below 'referenceDistance', gain is clamped.
+   | ExponentDistance
+   -- ^ Exponential distance rolloff model, modeling an exponential dropoff in
+   --   gain as distance increases between the source and listener.
+   --
+   --   /gain/ = (/distance/ \/ 'referenceDistance') \*\* (- 'rolloffFactor')
+   | ExponentDistanceClamped
+   -- ^ Exponential Distance clamped model, which is the exponential model,
+   --   extended to guarantee that for distances below 'referenceDistance',
+   --   gain is clamped.
+   deriving ( Eq, Ord, Show )
+
+marshalDistanceModel :: DistanceModel -> ALenum
+marshalDistanceModel x = case x of
+   NoAttenuation -> al_NONE
+   InverseDistance -> al_INVERSE_DISTANCE
+   InverseDistanceClamped -> al_INVERSE_DISTANCE_CLAMPED
+   LinearDistance -> al_LINEAR_DISTANCE
+   LinearDistanceClamped -> al_LINEAR_DISTANCE_CLAMPED
+   ExponentDistance -> al_EXPONENT_DISTANCE
+   ExponentDistanceClamped -> al_EXPONENT_DISTANCE_CLAMPED
+
+unmarshalDistanceModel :: ALenum -> DistanceModel
+unmarshalDistanceModel x
+   | x == al_NONE = NoAttenuation
+   | x == al_INVERSE_DISTANCE = InverseDistance
+   | x == al_INVERSE_DISTANCE_CLAMPED = InverseDistanceClamped
+   | x == al_LINEAR_DISTANCE = LinearDistance
+   | x == al_LINEAR_DISTANCE_CLAMPED = LinearDistanceClamped
+   | x == al_EXPONENT_DISTANCE = ExponentDistance
+   | x == al_EXPONENT_DISTANCE_CLAMPED = ExponentDistanceClamped
+   | otherwise = error ("unmarshalDistanceModel: illegal value " ++ show x)
+
+-- | Contains the current per-context distance model.
+
+distanceModel :: StateVar DistanceModel
+distanceModel =
+   makeStateVar
+      (alloca $ \buf -> do
+          alGetIntegerv (marshalGetPName GetDistanceModel) buf
+          peek1 (unmarshalDistanceModel . fromIntegral) buf)
+      (alDistanceModel . marshalDistanceModel)
+
+foreign import ccall unsafe "alGetIntegerv"
+   alGetIntegerv :: ALenum -> Ptr ALint -> IO ()
+
+foreign import ccall unsafe "alDistanceModel"
+   alDistanceModel :: ALenum -> IO ()
diff --git a/src/Sound/OpenAL/AL/BasicTypes.hs b/src/Sound/OpenAL/AL/BasicTypes.hs
new file mode 100644
--- /dev/null
+++ b/src/Sound/OpenAL/AL/BasicTypes.hs
@@ -0,0 +1,49 @@
+--------------------------------------------------------------------------------
+-- |
+-- Module      :  Sound.OpenAL.AL.BasicTypes
+-- Copyright   :  (c) Sven Panne 2003-2013
+-- License     :  BSD3
+-- 
+-- Maintainer  :  Sven Panne <svenpanne@gmail.com>
+-- Stability   :  stable
+-- Portability :  portable
+--
+-- This module corresponds to section 2.2 (Primitive Types) of the OpenAL
+-- Specification and Reference (version 1.1).
+--
+--------------------------------------------------------------------------------
+
+module Sound.OpenAL.AL.BasicTypes (
+   -- * Primitive Types
+   -- $PrimitiveTypes
+
+   -- * Floating-Point Computation
+   -- $FloatingPointComputation
+
+   ALboolean, ALchar, ALbyte, ALubyte, ALshort, ALushort, ALint, ALuint,
+   ALsizei, ALenum, ALfloat, ALdouble
+) where
+
+import Sound.OpenAL.Config
+
+--------------------------------------------------------------------------------
+-- $PrimitiveTypes
+-- As OpenAL is meant to allow for seamless integration with OpenGL code if
+-- needed, the OpenAL library primitive (scalar) data types mimic the OpenGL
+-- data types. Guaranteed minimum sizes are stated for OpenGL data types, but
+-- the actual choice of C data type is left to the implementation. All
+-- implementations on a given binary architecture, however, must use a common
+-- definition of these data types.
+ 
+--------------------------------------------------------------------------------
+-- $FloatingPointComputation
+-- Any representable floating-point value is legal as input to an OpenAL command
+-- that requires floating point data. The result of providing a value that is
+-- not a floating point number to such a command is unspecified, but must not
+-- lead to OpenAL being interrupted or terminated. In IEEE arithmetic, for
+-- example, providing a negative zero or a denormalized number to an OpenAL
+-- command yields predictable results, while providing a NaN or infinity yields
+-- unspecified results.  Some calculations require division. In such cases
+-- (including implied divisions required by vector normalizations), a division
+-- by zero produces an unspecified result but must not lead to OpenAL
+-- interruption or termination.
diff --git a/src/Sound/OpenAL/AL/Buffer.hs b/src/Sound/OpenAL/AL/Buffer.hs
new file mode 100644
--- /dev/null
+++ b/src/Sound/OpenAL/AL/Buffer.hs
@@ -0,0 +1,169 @@
+{-# OPTIONS_GHC -fno-warn-unused-imports #-}
+--------------------------------------------------------------------------------
+-- |
+-- Module      :  Sound.OpenAL.AL.Buffer
+-- Copyright   :  (c) Sven Panne 2003-2013
+-- License     :  BSD3
+-- 
+-- Maintainer  :  Sven Panne <svenpanne@gmail.com>
+-- Stability   :  stable
+-- Portability :  portable
+--
+-- This module corresponds to chapter 6 (Buffers) of the OpenAL Specification
+-- and Reference (version 1.1).
+--
+-- A buffer encapsulates OpenAL state related to storing sample data. The
+-- application can request and release buffer objects, and fill them with
+-- data. Data can be supplied compressed and encoded as long as the format is
+-- supported. Buffers can, internally, contain waveform data as uncompressed or
+-- compressed samples.
+-- 
+-- Unlike source (see "Sound.OpenAL.AL.Source") and listener (see
+-- "Sound.OpenAL.AL.Listener") objects, buffer objects can be shared among AL
+-- contexts. Buffers are referenced by sources. A single buffer can be referred
+-- to by multiple sources. This separation allows drivers and hardware to
+-- optimize storage and processing where applicable.
+-- 
+-- The simplest supported format for buffer data is PCM. PCM data is assumed to
+-- use the processor\'s native byte order. Other formats use the byte order
+-- native to that format.
+-- 
+-- At this time, buffer states are defined for purposes of discussion. The
+-- states described in this section are not exposed through the API (can not be
+-- queried, or be set directly), and the state description used in the
+-- implementation might differ from this.
+--
+-- A buffer is considered to be in one of the following states, with respect to
+-- all sources:
+--
+-- [/unused/] The buffer is not included in any queue for any source. In
+-- particular, the buffer is neither pending nor current for any source. The
+-- buffer name can be deleted at this time.
+--
+-- [/processed/] The buffer is listed in the queue of at least one source, but
+-- is neither pending nor current for any source. The buffer can be deleted as
+-- soon as it has been unqueued for all sources it is queued with.
+--
+-- [/pending/] There is at least one source for which the buffer has been queued,
+-- for which the buffer data has not yet been dereferenced. The buffer can only
+-- be unqueued for those sources that have dereferenced the data in the buffer
+-- in its entirety, and cannot be deleted or changed.
+--
+-- The buffer state is dependent on the state of all sources that is has been
+-- queued for. A single queue occurrence of a buffer propagates the buffer state
+-- (over all sources) from /unused/ to /processed/ or higher. Sources that are
+-- in the 'Stopped' or 'Initial' states still have queue entries that cause
+-- buffers to be /processed/.
+-- 
+-- A single queue entry with a single source for which the buffer is not yet
+-- /processed/ propagates the buffer\'s queuing state to /pending/.
+-- 
+-- Buffers that are /processed/ for a given source can be unqueued from that
+-- source\'s queue. Buffers that have been unqueued from all sources are
+-- /unused/. Buffers that are /unused/ can be deleted, or changed by writing
+-- 'bufferData'.
+--
+--------------------------------------------------------------------------------
+
+module Sound.OpenAL.AL.Buffer (
+   Buffer, MemoryRegion(..), Format(..), BufferData(..), bufferData
+) where
+
+import Foreign.C.Types
+import Foreign.Marshal.Alloc
+import Foreign.Ptr
+import Graphics.Rendering.OpenGL.GL.StateVar
+import Sound.OpenAL.AL.BasicTypes
+import Sound.OpenAL.AL.BufferInternal
+import Sound.OpenAL.AL.Format
+import Sound.OpenAL.AL.PeekPoke
+import Sound.OpenAL.ALC.Context ( Frequency )
+import Sound.OpenAL.Constants
+
+-- For Haddock only.
+import Sound.OpenAL.AL.Errors
+import Sound.OpenAL.AL.SourceState
+
+--------------------------------------------------------------------------------
+
+data MemoryRegion a = MemoryRegion (Ptr a) ALsizei
+   deriving ( Eq, Ord, Show )
+
+data BufferData a = BufferData (MemoryRegion a) Format Frequency
+   deriving ( Eq, Ord, Show )
+
+--------------------------------------------------------------------------------
+
+-- | A special case of buffer state is the actual sound sample data stored in
+-- association with the buffer. Applications can specify sample data using
+-- 'bufferData'.
+--
+-- The data specified is copied to an internal software, or if possible,
+-- hardware buffer. The implementation is free to apply decompression,
+-- conversion, resampling, and filtering as needed. The internal format of the
+-- buffer is not exposed to the application, and not accessible.
+--
+-- Buffers containing audio data with more than one channel will be played
+-- without 3D spatialization features, these formats are normally used for
+-- background music. Applications should always check for an error condition
+-- after attempting to specify buffer data in case an implementation has to
+-- generate an 'ALOutOfMemory' or a conversion related 'ALInvalidValue' error.
+-- The application is free to reuse the memory specified by the data pointer
+-- once 'bufferData' is set. The implementation has to dereference, e.g. copy,
+-- the data while accessing 'bufferData' execution.
+
+bufferData :: Buffer -> StateVar (BufferData a)
+bufferData buffer = makeStateVar (getBufferData buffer) (setBufferData buffer)
+
+getBufferData :: Buffer -> IO (BufferData a)
+getBufferData buffer = do
+   channels <- getBufferi buffer Channels
+   bits <- getBufferi buffer Bits
+   raw <- return nullPtr -- ToDo: AL_DATA query missing!!!
+   size <- getBufferi buffer Size
+   frequency <- getBufferi buffer Frequency
+   return $ BufferData (MemoryRegion  raw size) (makeFormat channels bits) frequency
+
+setBufferData :: Buffer -> BufferData a -> IO ()
+setBufferData buffer (BufferData (MemoryRegion raw size) format frequency) =
+      alBufferData buffer (marshalFormat format) raw size (round frequency)
+
+foreign import ccall unsafe "alBufferData"
+   alBufferData :: Buffer -> ALenum -> Ptr a -> ALsizei -> ALsizei -> IO ()
+
+--------------------------------------------------------------------------------
+
+-- ToDo: What about IMAADPCMMono16, IMAADPCMStereo16, Vorbis...?
+makeFormat :: ALint -> ALint -> Format
+makeFormat 1  8 = Mono8
+makeFormat 2  8 = Stereo8
+makeFormat 1 16 = Mono16
+makeFormat 2 16 = Stereo16
+makeFormat channels bits =
+   error ("makeFormat: illegal values " ++ show (channels, bits))
+
+--------------------------------------------------------------------------------
+
+data BufferQuery =
+     Frequency
+   | Size
+   | Bits
+   | Channels
+
+marshalBufferQuery :: BufferQuery -> ALenum
+marshalBufferQuery x = case x of
+   Frequency -> al_FREQUENCY
+   Size -> al_SIZE
+   Bits -> al_BITS
+   Channels -> al_CHANNELS
+
+--------------------------------------------------------------------------------
+
+getBufferi :: Num a => Buffer -> BufferQuery -> IO a
+getBufferi buffer query =
+   alloca $ \buf -> do
+      alGetBufferi buffer (marshalBufferQuery query) buf
+      peek1 fromIntegral buf
+
+foreign import ccall unsafe "alGetBufferi"
+   alGetBufferi :: Buffer -> ALenum -> Ptr ALint -> IO ()
diff --git a/src/Sound/OpenAL/AL/BufferInternal.hs b/src/Sound/OpenAL/AL/BufferInternal.hs
new file mode 100644
--- /dev/null
+++ b/src/Sound/OpenAL/AL/BufferInternal.hs
@@ -0,0 +1,77 @@
+{-# OPTIONS_HADDOCK hide #-}
+--------------------------------------------------------------------------------
+-- |
+-- Module      :  Sound.OpenAL.AL.BufferInternal
+-- Copyright   :  (c) Sven Panne 2003-2013
+-- License     :  BSD3
+-- 
+-- Maintainer  :  Sven Panne <svenpanne@gmail.com>
+-- Stability   :  stable
+-- Portability :  portable
+--
+-- This is a purely internal module for (un-)marshaling Buffer.
+--
+--------------------------------------------------------------------------------
+
+module Sound.OpenAL.AL.BufferInternal (
+   Buffer(..), marshalBuffer, unmarshalBuffer
+) where
+
+import Graphics.Rendering.OpenGL.GL.ObjectName
+import Foreign.Marshal.Array ( withArrayLen, peekArray, allocaArray )
+import Foreign.C.Types
+import Foreign.Ptr ( Ptr, castPtr )
+import Foreign.Storable ( Storable(..) )
+import Sound.OpenAL.AL.ALboolean ( unmarshalALboolean )
+import Sound.OpenAL.AL.BasicTypes ( ALboolean, ALuint, ALsizei )
+import Sound.OpenAL.AL.PeekPoke ( peek1, poke1 )
+
+--------------------------------------------------------------------------------
+
+-- | The abstract buffer type.
+
+newtype Buffer = Buffer { bufferID :: ALuint }
+   deriving ( Eq, Ord, Show )
+ 
+-- | A dummy buffer.
+
+nullBuffer :: Buffer
+nullBuffer = Buffer 0
+
+marshalBuffer :: Maybe Buffer -> ALuint
+marshalBuffer = bufferID . maybe nullBuffer id
+
+unmarshalBuffer :: ALuint -> Maybe Buffer
+unmarshalBuffer b =
+   if b == bufferID nullBuffer then Nothing else Just (Buffer b)
+
+instance Storable Buffer where
+   sizeOf    ~(Buffer b) = sizeOf b
+   alignment ~(Buffer b) = alignment b
+   peek                  = peek1 Buffer . castPtr
+   poke ptr   (Buffer b) = poke1 (castPtr ptr) b
+
+--------------------------------------------------------------------------------
+-- This should really be in Sound.OpenAL.AL.Buffer, but we have it here to
+-- avoid an orphan module.
+
+instance ObjectName Buffer where
+   deleteObjectNames buffers =
+      withArrayLen buffers $ alDeleteBuffers . fromIntegral
+
+   isObjectName = fmap unmarshalALboolean . alIsBuffer
+
+instance GeneratableObjectName Buffer where
+   genObjectNames n =
+      allocaArray n $ \buf -> do
+        alGenBuffers (fromIntegral n) buf
+        peekArray n buf
+
+foreign import ccall unsafe "alGenBuffers"
+   alGenBuffers :: ALsizei -> Ptr Buffer -> IO ()
+
+foreign import ccall unsafe "alDeleteBuffers"
+   alDeleteBuffers :: ALsizei -> Ptr Buffer -> IO ()
+
+foreign import ccall unsafe "alIsBuffer"
+   alIsBuffer :: Buffer -> IO ALboolean
diff --git a/src/Sound/OpenAL/AL/Doppler.hs b/src/Sound/OpenAL/AL/Doppler.hs
new file mode 100644
--- /dev/null
+++ b/src/Sound/OpenAL/AL/Doppler.hs
@@ -0,0 +1,91 @@
+{-# OPTIONS_GHC -fno-warn-unused-imports #-}
+--------------------------------------------------------------------------------
+-- |
+-- Module      :  Sound.OpenAL.AL.Doppler
+-- Copyright   :  (c) Sven Panne 2003-2013
+-- License     :  BSD3
+-- 
+-- Maintainer  :  Sven Panne <svenpanne@gmail.com>
+-- Stability   :  stable
+-- Portability :  portable
+--
+-- This module corresponds to section 3.5.2. (Velocity Dependent Doppler Effect)
+-- of the OpenAL Specification and Reference (version 1.1).
+-- 
+--------------------------------------------------------------------------------
+
+module Sound.OpenAL.AL.Doppler (
+   -- * Introduction
+   -- $Introduction
+   dopplerFactor, speedOfSound
+) where
+
+import Foreign.C.Types
+import Foreign.Ptr
+import Graphics.Rendering.OpenGL.GL.StateVar
+import Sound.OpenAL.AL.BasicTypes
+import Sound.OpenAL.AL.Extensions
+import Sound.OpenAL.AL.QueryUtils
+
+-- For Haddock only.
+import Sound.OpenAL.AL.Errors
+
+--------------------------------------------------------------------------------
+
+-- | 'dopplerFactor' is a simple scaling of source and listener velocities to
+-- exaggerate or deemphasize the Doppler (pitch) shift resulting from the
+-- calculation. Setting 'dopplerFactor' to a negative value will result in an
+-- 'ALInvalidValue' error, the command is then ignored. The default value is 1.
+-- The implementation is free to optimize the case of 'dopplerFactor' containing
+-- zero, as this effectively disables the effect.
+
+dopplerFactor :: StateVar ALfloat
+dopplerFactor = makeDopplerVar GetDopplerFactor "alDopplerFactor"
+
+--------------------------------------------------------------------------------
+
+-- | 'speedOfSound' allows the application to change the reference (propagation)
+-- speed used in the Doppler calculation. The source and listener velocities
+-- should be expressed in the same units as the speed of sound. Setting
+-- 'speedOfSound' to a negative or zero value will result in an 'ALInvalidValue'
+-- error, the command is ignored then. The default value is 343.3 (appropriate
+-- for velocity units of meters and air as the propagation medium).
+
+speedOfSound :: StateVar ALfloat
+speedOfSound = makeDopplerVar GetSpeedOfSound "alSpeedOfSound"
+
+--------------------------------------------------------------------------------
+
+makeDopplerVar :: GetPName -> String -> StateVar ALfloat
+makeDopplerVar p apiEntryName =
+   makeStateVar
+      (alGetFloat (marshalGetPName p))
+      (\value -> do
+         -- ToDo: Should we check alcVersion or alIsExtensionPresent here?
+         funPtr <- get (alProcAddress apiEntryName)
+         invokeWithFloat funPtr value)
+
+foreign import ccall unsafe "alGetFloat"
+   alGetFloat :: ALenum -> IO ALfloat
+
+type Invoker a = FunPtr a -> a
+
+foreign import ccall unsafe "dynamic"
+   invokeWithFloat :: Invoker (ALfloat -> IO ()) 
+
+--------------------------------------------------------------------------------
+-- $Introduction
+-- The Doppler Effect depends on the velocities of source and listener relative
+-- to the medium, and the propagation speed of sound in that medium.  The
+-- application might want to emphasize or de-emphasize the Doppler Effect as
+-- physically accurate calculation might not give the desired results.
+-- The amount of frequency shift (pitch change) is proportional to the speed of
+-- listener and source along their line of sight.
+-- 
+-- The Doppler Effect as implemented by OpenAL is described in detail in section
+-- 3.5.2 of the OpenAL 1.1 specification. Note that effects of the medium (air,
+-- water) moving with respect to listener and source are ignored. There are two
+-- API calls global to the current context that provide control of the Doppler
+-- factor and the speed of sound. Distance and velocity units are completely
+-- independent of one another (so you could use different units for each if
+-- desired).
diff --git a/src/Sound/OpenAL/AL/Errors.hs b/src/Sound/OpenAL/AL/Errors.hs
new file mode 100644
--- /dev/null
+++ b/src/Sound/OpenAL/AL/Errors.hs
@@ -0,0 +1,88 @@
+--------------------------------------------------------------------------------
+-- |
+-- Module      :  Sound.OpenAL.AL.Errors
+-- Copyright   :  (c) Sven Panne 2003-2013
+-- License     :  BSD3
+-- 
+-- Maintainer  :  Sven Panne <svenpanne@gmail.com>
+-- Stability   :  stable
+-- Portability :  portable
+--
+-- This module corresponds to section 2.7 (AL Errors) of the OpenAL
+-- Specification and Reference (version 1.1).
+--
+--------------------------------------------------------------------------------
+
+module Sound.OpenAL.AL.Errors (
+   ALError(..), ALErrorCategory(..), alErrors
+) where
+
+import Foreign.C.Types
+import Graphics.Rendering.OpenGL.GL.StateVar
+import Sound.OpenAL.AL.BasicTypes ( ALenum )
+import Sound.OpenAL.Constants (
+   al_NO_ERROR, al_INVALID_NAME, al_INVALID_ENUM, al_INVALID_VALUE,
+   al_INVALID_OPERATION, al_OUT_OF_MEMORY )
+import Sound.OpenAL.AL.QueryUtils ( StringName(..), getString )
+
+--------------------------------------------------------------------------------
+
+-- | AL errors consist of a general error category and a description of what
+-- went wrong.
+
+data ALError = ALError ALErrorCategory String
+   deriving ( Eq, Ord, Show )
+
+--------------------------------------------------------------------------------
+
+-- | General AL error categories.
+
+data ALErrorCategory =
+     ALInvalidEnum
+   | ALInvalidValue
+   | ALInvalidOperation
+   | ALInvalidName
+   | ALOutOfMemory
+   deriving ( Eq, Ord, Show )
+
+unmarshalALErrorCategory :: ALenum -> ALErrorCategory
+unmarshalALErrorCategory x
+   | x == al_INVALID_ENUM = ALInvalidEnum
+   | x == al_INVALID_VALUE = ALInvalidValue
+   | x == al_INVALID_OPERATION = ALInvalidOperation
+   | x == al_INVALID_NAME = ALInvalidName
+   | x == al_OUT_OF_MEMORY = ALOutOfMemory
+   | otherwise = error ("unmarshalALErrorCategory: illegal value " ++ show x)
+
+--------------------------------------------------------------------------------
+
+-- | OpenAL detects only a subset of those conditions that could be considered
+-- errors. This is because in many cases error checking would adversely impact
+-- the performance of an error-free program. The state variable 'alErrors' is
+-- used to obtain error information. When an error is detected by AL, a flag is
+-- set and the error code is recorded. Further errors, if they occur, do not
+-- affect this recorded code. When 'alErrors' is read, the error is returned and
+-- the flag is cleared, so that a further error will again record its code. If
+-- reading 'alErrors' returns @\[\]@ then there has been no detectable error
+-- since the last time 'alErrors' (or since the AL was initialized).
+--
+-- When an error flag is set, results of AL operations are undefined only if
+-- 'ALOutOfMemory' has occurred. In other cases, the command generating the
+-- error is ignored so that it has no effect on AL state or output buffer
+-- contents. If the error generating command returns a value, it returns zero.
+-- If the generating command modifies values through a pointer argument, no
+-- change is made to these values. These error semantics apply only to AL
+-- errors, not to system errors such as memory access errors.
+
+alErrors :: GettableStateVar [ALError]
+alErrors =
+   makeGettableStateVar $ do
+      c <- alGetError
+      if c == al_NO_ERROR
+         then return []
+         else do
+            s <- getString (ALErrorCategory c)
+            return [ ALError (unmarshalALErrorCategory c) s ]
+
+foreign import ccall unsafe "alGetError"
+   alGetError :: IO ALenum
diff --git a/src/Sound/OpenAL/AL/Extensions.hs b/src/Sound/OpenAL/AL/Extensions.hs
new file mode 100644
--- /dev/null
+++ b/src/Sound/OpenAL/AL/Extensions.hs
@@ -0,0 +1,104 @@
+--------------------------------------------------------------------------------
+-- |
+-- Module      :  Sound.OpenAL.AL.Extensions
+-- Copyright   :  (c) Sven Panne 2003-2013
+-- License     :  BSD3
+-- 
+-- Maintainer  :  Sven Panne <svenpanne@gmail.com>
+-- Stability   :  stable
+-- Portability :  portable
+--
+-- This module corresponds to section 3.1.2 (String Queries) and chapter 7
+-- (Appendix: Extensions) of the OpenAL Specification and Reference (version
+-- 1.1).
+--
+--------------------------------------------------------------------------------
+
+module Sound.OpenAL.AL.Extensions (
+   -- * General AL extension support
+   alExtensions, alIsExtensionPresent, alProcAddress, alEnumValue, alVersion,
+
+   -- * Internal re-exports, use at your own risk
+   unmarshalALboolean, unmarshalFormat, unmarshalBuffer
+) where
+
+import Foreign.C.Types
+import Foreign.Ptr
+import Graphics.Rendering.OpenGL.GL.StateVar
+import Sound.OpenAL.AL.ALboolean
+import Sound.OpenAL.AL.BasicTypes
+import Sound.OpenAL.AL.BufferInternal
+import Sound.OpenAL.AL.Format
+import Sound.OpenAL.AL.QueryUtils
+import Sound.OpenAL.AL.String
+
+--------------------------------------------------------------------------------
+
+-- | Contains the list of available extensions.
+
+alExtensions :: GettableStateVar [String]
+alExtensions = makeGettableStateVar (fmap words $ getString Extensions)
+
+--------------------------------------------------------------------------------
+
+-- | Contains a version string in the format @\"/\<spec major number\>/./\<spec
+-- minor number\>/ /\<optional vendor version information\>/\"@.
+
+alVersion :: GettableStateVar String
+alVersion = makeGettableStateVar (getString Version)
+
+--------------------------------------------------------------------------------
+
+-- | To verify that a given extension is available for the current context, use
+-- 'alIsExtensionPresent'. For invalid and unsupported string tokens it contains
+-- 'False'. The extension name is not case sensitive: The implementation will
+-- convert the name to all upper-case internally (and will express extension
+-- names in upper-case).
+
+alIsExtensionPresent :: String -> GettableStateVar Bool
+alIsExtensionPresent extensionName =
+   makeGettableStateVar $
+      fmap unmarshalALboolean $
+         withALString extensionName alIsExtensionPresent_
+
+foreign import ccall unsafe "alIsExtensionPresent"
+   alIsExtensionPresent_ :: Ptr ALchar -> IO ALboolean
+
+--------------------------------------------------------------------------------
+
+-- | To retrieving function entry addresses, applications can use
+-- 'alProcAddress'. It contains 'nullFunPtr' if no entry point with the given
+-- name can be found. Implementations are free to use 'nullFunPtr' if an
+-- entry point is present, but not applicable for the current context. However
+-- the specification does not guarantee this behavior. Applications can use
+-- 'alProcAddress' to obtain core API entry points, not just extensions. This
+-- is the recommended way to dynamically load and unload OpenAL DLLs as sound
+-- drivers.
+
+alProcAddress :: String -> GettableStateVar (FunPtr a)
+alProcAddress funcName = makeGettableStateVar $
+   withALString funcName alGetProcAddress
+
+foreign import ccall unsafe "alGetProcAddress"
+   alGetProcAddress :: Ptr ALchar -> IO (FunPtr a)
+
+--------------------------------------------------------------------------------
+
+-- | To obtain enumeration values for extensions, the application has to use
+-- 'alEnumValue' of an extension token. Enumeration values are defined within
+-- the OpenAL name space and allocated according to specification of the core
+-- API and the extensions, thus they are context-independent.
+--
+-- 'alEnumValue' contains 0 if the enumeration can not be found. The presence of
+-- an enum value does not guarantee the applicability of an extension to the
+-- current context. A non-zero value indicates merely that the implementation is
+-- aware of the existence of this extension. Implementations should not attempt
+-- to use 0 to indicate that the extensions is not supported for the current
+-- context.
+
+alEnumValue :: String -> GettableStateVar ALenum
+alEnumValue enumName = makeGettableStateVar $
+   withALString enumName alGetEnumValue
+
+foreign import ccall unsafe "alGetEnumValue"
+   alGetEnumValue :: Ptr ALchar -> IO ALenum
diff --git a/src/Sound/OpenAL/AL/Format.hs b/src/Sound/OpenAL/AL/Format.hs
new file mode 100644
--- /dev/null
+++ b/src/Sound/OpenAL/AL/Format.hs
@@ -0,0 +1,50 @@
+{-# OPTIONS_HADDOCK hide #-}
+--------------------------------------------------------------------------------
+-- |
+-- Module      :  Sound.OpenAL.AL.Format
+-- Copyright   :  (c) Sven Panne 2003-2013
+-- License     :  BSD3
+-- 
+-- Maintainer  :  Sven Panne <svenpanne@gmail.com>
+-- Stability   :  stable
+-- Portability :  portable
+--
+-- This is a purely internal module for (un-)marshaling Format.
+--
+--------------------------------------------------------------------------------
+
+module Sound.OpenAL.AL.Format (
+   Format(..), marshalFormat, unmarshalFormat
+) where
+
+import Sound.OpenAL.AL.BasicTypes ( ALenum )
+import Sound.OpenAL.Constants (
+   al_FORMAT_MONO8, al_FORMAT_MONO16, al_FORMAT_STEREO8, al_FORMAT_STEREO16 )
+
+--------------------------------------------------------------------------------
+
+-- | Valid sound formats. An implementation may expose other formats, see
+-- "Sound.OpenAL.ALC.Extensions" for information on determining if additional
+-- formats are supported.
+
+data Format =
+     Mono8
+   | Mono16
+   | Stereo8
+   | Stereo16
+   deriving ( Eq, Ord, Show )
+
+marshalFormat :: Format -> ALenum
+marshalFormat x = case x of
+   Mono8 -> al_FORMAT_MONO8
+   Mono16 -> al_FORMAT_MONO16
+   Stereo8 -> al_FORMAT_STEREO8
+   Stereo16 -> al_FORMAT_STEREO16
+
+unmarshalFormat :: ALenum -> Format
+unmarshalFormat x
+   | x == al_FORMAT_MONO8 = Mono8
+   | x == al_FORMAT_MONO16 = Mono16
+   | x == al_FORMAT_STEREO8 = Stereo8
+   | x == al_FORMAT_STEREO16 = Stereo16
+   | otherwise = error ("unmarshalFormat: illegal value " ++ show x)
diff --git a/src/Sound/OpenAL/AL/Listener.hs b/src/Sound/OpenAL/AL/Listener.hs
new file mode 100644
--- /dev/null
+++ b/src/Sound/OpenAL/AL/Listener.hs
@@ -0,0 +1,149 @@
+--------------------------------------------------------------------------------
+-- |
+-- Module      :  Sound.OpenAL.AL.Listener
+-- Copyright   :  (c) Sven Panne 2003-2013
+-- License     :  BSD3
+-- 
+-- Maintainer  :  Sven Panne <svenpanne@gmail.com>
+-- Stability   :  stable
+-- Portability :  portable
+--
+-- This module corresponds to sections 4.1 (Basic Listener and Source
+-- Attributes) and 4.2 (Listener Object) of the OpenAL Specification and
+-- Reference (version 1.1).
+-- 
+-- The listener object defines various properties that affect processing of the
+-- sound for the actual output. The listener is unique for an OpenAL Context,
+-- and has no name. By controlling the listener, the application controls the
+-- way the user experiences the virtual world, as the listener defines the
+-- sampling\/pickup point and orientation, and other parameters that affect the
+-- output stream.
+-- 
+-- It is entirely up to the driver and hardware configuration, i.e. the
+-- installation of OpenAL as part of the operating system and hardware setup,
+-- whether the output stream is generated for headphones or 2 speakers, 4.1
+-- speakers, or other arrangements, whether (and which) HRTFs are applied,
+-- etc...
+--
+---------------------------------------------------------------------------------
+
+module Sound.OpenAL.AL.Listener (
+   listenerPosition, listenerVelocity, Gain, listenerGain, orientation
+) where
+
+import Graphics.Rendering.OpenGL.GL.StateVar
+import Graphics.Rendering.OpenGL.GL.Tensor
+import Foreign.C.Types
+import Foreign.Marshal.Array
+import Foreign.Marshal.Utils
+import Foreign.Ptr
+import Foreign.Storable
+import Sound.OpenAL.AL.BasicTypes
+import Sound.OpenAL.AL.PeekPoke
+import Sound.OpenAL.AL.QueryUtils
+
+--------------------------------------------------------------------------------
+
+-- | 'listenerPosition' contains the current location of the listener in the
+-- world coordinate system. Any 3-tuple of valid float values is allowed.
+-- Implementation behavior on encountering NaN and infinity is not defined. The
+-- initial position is ('Vertex3' 0 0 0).
+
+listenerPosition :: StateVar (Vertex3 ALfloat)
+listenerPosition = makeListenerVar GetPosition 3 (peek3 Vertex3) listener3f
+
+--------------------------------------------------------------------------------
+
+-- | 'listenerVelocity' contains current velocity (speed and direction) of the
+-- listener in the world coordinate system. Any 3-tuple of valid float
+-- values is allowed, and the initial velocity is ('Vector3' 0 0 0).
+-- 'listenerVelocity' does not affect 'listenerPosition'. OpenAL does not
+-- calculate the velocity from subsequent position updates, nor does it
+-- adjust the position over time based on the specified velocity. Any
+-- such calculation is left to the application. For the purposes of sound
+-- processing, position and velocity are independent parameters affecting
+-- different aspects of the sounds.
+--
+-- 'listenerVelocity' is taken into account by the driver to synthesize the
+-- Doppler effect perceived by the listener for each source, based on the
+-- velocity of both source and listener, and the Doppler related parameters.
+
+listenerVelocity :: StateVar (Vector3 ALfloat)
+listenerVelocity = makeListenerVar GetVelocity 3 (peek3 Vector3) listener3f
+
+--------------------------------------------------------------------------------
+
+-- | A scalar amplitude multiplier.
+type Gain = ALfloat
+
+-- | 'listenerGain' contains a scalar amplitude multiplier, which is effectively
+-- applied to all sources in the current context. The initial value 1 means
+-- that the sound is unattenuated. A 'listenerGain' value of 0.5 is equivalent
+-- to an attenuation of 6dB. The value zero equals silence (no output). Driver
+-- implementations are free to optimize this case and skip mixing and processing
+-- stages where applicable. The implementation is in charge of ensuring
+-- artifact-free (click-free) changes of gain values and is free to defer actual
+-- modification of the sound samples, within the limits of acceptable latencies.
+--
+-- A 'listenerGain' larger than 1 (amplification) is permitted. However, the
+-- implementation is free to clamp the total gain (effective gain per source
+-- times listener gain) to 1 to prevent overflow.
+
+listenerGain :: StateVar Gain
+listenerGain = makeListenerVar GetGain 1 (peek1 id) listenerf
+
+--------------------------------------------------------------------------------
+
+-- | 'orientation' contains an \"at\" vector and an \"up\" vector, where the
+-- \"at\" vector represents the \"forward\" direction of the listener and the
+-- orthogonal projection of the \"up\" vector into the subspace perpendicular to
+-- the \"at\" vector represents the \"up\" direction for the listener. OpenAL
+-- expects two vectors that are linearly independent. These vectors are not
+-- expected to be normalized. If the two vectors are linearly dependent,
+-- behavior is undefined. The initial orientation is ('Vector3' 0 0 (-1),
+-- 'Vector3' 0 1 0), i.e. looking down the Z axis with the Y axis pointing
+-- upwards.
+
+orientation :: StateVar (Vector3 ALfloat, Vector3 ALfloat)
+orientation = makeListenerVar GetOrientation 6 (peek6 Vector3) listenerVector6
+
+--------------------------------------------------------------------------------
+
+listenerf :: GetPName -> ALfloat -> IO ()
+listenerf = alListenerf . marshalGetPName
+
+foreign import ccall unsafe "alListenerf"
+   alListenerf :: ALenum -> ALfloat -> IO ()
+
+--------------------------------------------------------------------------------
+
+listener3f :: Storable a => GetPName -> a -> IO ()
+listener3f n x = with x $ listenerfv n
+
+listenerVector6 :: GetPName -> (Vector3 ALfloat, Vector3 ALfloat) -> IO ()
+listenerVector6 n (x, y) = withArray [x, y] $ listenerfv n
+
+listenerfv :: GetPName -> Ptr a -> IO ()
+listenerfv = alListenerfv . marshalGetPName
+
+foreign import ccall unsafe "alListenerfv"
+   alListenerfv :: ALenum -> Ptr a -> IO ()
+
+--------------------------------------------------------------------------------
+
+getListenerfv :: GetPName -> Ptr ALfloat -> IO ()
+getListenerfv = alGetListenerfv . marshalGetPName
+
+foreign import ccall unsafe "alGetListenerfv"
+   alGetListenerfv :: ALenum -> Ptr ALfloat -> IO ()
+
+--------------------------------------------------------------------------------
+
+makeListenerVar :: GetPName -> Int -> (Ptr ALfloat -> IO a)
+                -> (GetPName -> a -> IO ()) -> StateVar a
+makeListenerVar pname size reader writer =
+   makeStateVar
+      (allocaArray size $ \buf -> do
+          getListenerfv pname buf
+          reader buf)
+      (writer pname)
diff --git a/src/Sound/OpenAL/AL/PeekPoke.hs b/src/Sound/OpenAL/AL/PeekPoke.hs
new file mode 100644
--- /dev/null
+++ b/src/Sound/OpenAL/AL/PeekPoke.hs
@@ -0,0 +1,59 @@
+{-# OPTIONS_HADDOCK hide #-}
+--------------------------------------------------------------------------------
+-- |
+-- Module      :  Sound.OpenAL.AL.PeekPoke
+-- Copyright   :  (c) Sven Panne 2003-2013
+-- License     :  BSD3
+-- 
+-- Maintainer  :  Sven Panne <svenpanne@gmail.com>
+-- Stability   :  stable
+-- Portability :  portable
+--
+-- This is a purely internal module with peek- and poke-related utilities.
+--
+--------------------------------------------------------------------------------
+
+module Sound.OpenAL.AL.PeekPoke (
+   poke1, peek1, peek3, peek6
+) where
+
+import Foreign.Ptr ( Ptr )
+import Foreign.Storable ( Storable(peekElemOff,pokeElemOff) )
+
+--------------------------------------------------------------------------------
+-- The implementation is little bit verbose/redundant, but seems to generate
+-- better code than mapM/zipWithM_.
+
+--------------------------------------------------------------------------------
+
+{-# INLINE poke1 #-}
+poke1 :: Storable a => Ptr a -> a -> IO ()
+poke1 ptr x =
+   pokeElemOff ptr 0 x
+
+--------------------------------------------------------------------------------
+
+{-# INLINE peek1 #-}
+peek1 :: Storable a => (a -> b) -> Ptr a -> IO b
+peek1 f ptr = do
+   x <- peekElemOff ptr 0
+   return $ f x
+
+{-# INLINE peek3 #-}
+peek3 :: Storable a => (a -> a -> a -> b) -> Ptr a -> IO b
+peek3 f ptr = do
+   x <- peekElemOff ptr 0
+   y <- peekElemOff ptr 1
+   z <- peekElemOff ptr 2
+   return $ f x y z
+
+{-# INLINE peek6 #-}
+peek6 :: Storable a => (a -> a -> a -> b) -> Ptr a -> IO (b, b)
+peek6 f ptr = do
+   x <- peekElemOff ptr 0
+   y <- peekElemOff ptr 1
+   z <- peekElemOff ptr 2
+   u <- peekElemOff ptr 3
+   v <- peekElemOff ptr 4
+   w <- peekElemOff ptr 5
+   return $ (f x y z, f u v w)
diff --git a/src/Sound/OpenAL/AL/QueryUtils.hs b/src/Sound/OpenAL/AL/QueryUtils.hs
new file mode 100644
--- /dev/null
+++ b/src/Sound/OpenAL/AL/QueryUtils.hs
@@ -0,0 +1,123 @@
+{-# OPTIONS_HADDOCK hide #-}
+--------------------------------------------------------------------------------
+-- |
+-- Module      :  Sound.OpenAL.AL.QueryUtils
+-- Copyright   :  (c) Sven Panne 2003-2013
+-- License     :  BSD3
+-- 
+-- Maintainer  :  Sven Panne <svenpanne@gmail.com>
+-- Stability   :  stable
+-- Portability :  portable
+--
+-- This is a purely internal module with utilities to query OpenAL state.
+--
+--------------------------------------------------------------------------------
+
+module Sound.OpenAL.AL.QueryUtils (
+   GetPName(..), marshalGetPName,
+   StringName(..), getString
+) where
+
+import Foreign.C.Types
+import Foreign.Ptr ( Ptr )
+import Sound.OpenAL.AL.BasicTypes ( ALchar, ALenum )
+import Sound.OpenAL.AL.String ( peekALString )
+import Sound.OpenAL.Constants (
+   al_DISTANCE_MODEL, al_DOPPLER_FACTOR, al_SPEED_OF_SOUND, al_POSITION,
+   al_VELOCITY, al_GAIN, al_ORIENTATION, al_SOURCE_RELATIVE, al_SOURCE_TYPE,
+   al_LOOPING, al_BUFFER, al_BUFFERS_QUEUED, al_BUFFERS_PROCESSED, al_MIN_GAIN,
+   al_MAX_GAIN, al_REFERENCE_DISTANCE, al_ROLLOFF_FACTOR, al_MAX_DISTANCE,
+   al_PITCH, al_DIRECTION, al_CONE_INNER_ANGLE, al_CONE_OUTER_ANGLE,
+   al_CONE_OUTER_GAIN, al_SEC_OFFSET, al_SAMPLE_OFFSET, al_BYTE_OFFSET,
+   al_SOURCE_STATE, al_VENDOR, al_RENDERER, al_VERSION, al_EXTENSIONS )
+
+--------------------------------------------------------------------------------
+
+data GetPName =
+     GetDistanceModel
+   | GetDopplerFactor
+   | GetSpeedOfSound
+
+   | GetPosition
+
+   | GetVelocity
+   | GetGain
+
+   | GetOrientation
+
+   | GetSourceRelative
+   | GetSourceType
+   | GetLooping
+   | GetBuffer
+   | GetBuffersQueued
+   | GetBuffersProcessed
+   | GetMinGain
+   | GetMaxGain
+   | GetReferenceDistance
+   | GetRolloffFactor
+   | GetMaxDistance
+   | GetPitch
+   | GetDirection
+   | GetConeInnerAngle
+   | GetConeOuterAngle
+   | GetConeOuterGain
+   | GetSecOffset
+   | GetSampleOffset
+   | GetByteOffset
+   | GetSourceState
+
+marshalGetPName :: GetPName -> ALenum
+marshalGetPName x = case x of
+   GetDistanceModel -> al_DISTANCE_MODEL
+   GetDopplerFactor -> al_DOPPLER_FACTOR
+   GetSpeedOfSound -> al_SPEED_OF_SOUND
+
+   GetPosition -> al_POSITION
+   GetVelocity -> al_VELOCITY
+   GetGain -> al_GAIN
+
+   GetOrientation -> al_ORIENTATION
+
+   GetSourceRelative -> al_SOURCE_RELATIVE
+   GetSourceType -> al_SOURCE_TYPE
+   GetLooping -> al_LOOPING
+   GetBuffer -> al_BUFFER
+   GetBuffersQueued -> al_BUFFERS_QUEUED
+   GetBuffersProcessed -> al_BUFFERS_PROCESSED
+   GetMinGain -> al_MIN_GAIN
+   GetMaxGain -> al_MAX_GAIN
+   GetReferenceDistance -> al_REFERENCE_DISTANCE
+   GetRolloffFactor -> al_ROLLOFF_FACTOR
+   GetMaxDistance -> al_MAX_DISTANCE
+   GetPitch -> al_PITCH
+   GetDirection -> al_DIRECTION
+   GetConeInnerAngle -> al_CONE_INNER_ANGLE
+   GetConeOuterAngle -> al_CONE_OUTER_ANGLE
+   GetConeOuterGain -> al_CONE_OUTER_GAIN
+   GetSecOffset -> al_SEC_OFFSET
+   GetSampleOffset -> al_SAMPLE_OFFSET
+   GetByteOffset -> al_BYTE_OFFSET
+   GetSourceState -> al_SOURCE_STATE
+
+--------------------------------------------------------------------------------
+
+data StringName =
+     Vendor
+   | Renderer
+   | Version
+   | Extensions
+   | ALErrorCategory ALenum
+
+marshalStringName :: StringName -> ALenum
+marshalStringName x = case x of
+   Vendor -> al_VENDOR
+   Renderer -> al_RENDERER
+   Version -> al_VERSION
+   Extensions -> al_EXTENSIONS
+   ALErrorCategory e -> e
+
+getString :: StringName -> IO String
+getString n = alGetString (marshalStringName n) >>= peekALString 
+
+foreign import ccall unsafe "alGetString"
+   alGetString :: ALenum -> IO (Ptr ALchar)
diff --git a/src/Sound/OpenAL/AL/Source.hs b/src/Sound/OpenAL/AL/Source.hs
new file mode 100644
--- /dev/null
+++ b/src/Sound/OpenAL/AL/Source.hs
@@ -0,0 +1,767 @@
+{-# OPTIONS_GHC -fno-warn-unused-imports #-}
+--------------------------------------------------------------------------------
+-- |
+-- Module      :  Sound.OpenAL.AL.Source
+-- Copyright   :  (c) Sven Panne 2003-2013
+-- License     :  BSD3
+-- 
+-- Maintainer  :  Sven Panne <svenpanne@gmail.com>
+-- Stability   :  stable
+-- Portability :  portable
+--
+-- This module corresponds to sections 4.1 (Basic Listener and Source
+-- Attributes) and 4.3 (Source Objects) of the OpenAL Specification and
+-- Reference (version 1.1).
+--
+-- Sources specify attributes like position, velocity, and a buffer with sample
+-- data. By controlling a source\'s attributes the application can modify and
+-- parameterize the static sample data provided by the buffer referenced by the
+-- source. Sources define a localized sound, and encapsulate a set of attributes
+-- applied to a sound at its origin, i.e. in the very first stage of the
+-- processing on the way to the listener. Source related effects have to be
+-- applied before listener related effects unless the output is invariant to any
+-- collapse or reversal of order. OpenAL also provides additional functions to
+-- manipulate and query the execution state of sources: the current playing
+-- status of a source, including access to the current sampling position within
+-- the associated buffer.
+--
+--------------------------------------------------------------------------------
+
+module Sound.OpenAL.AL.Source (
+   -- * The Source Type
+   Source,
+
+   -- * Source Attributes
+
+   -- ** Basic Source Attributes
+   sourcePosition, sourceVelocity, sourceGain,
+
+   -- ** Source Positioning
+   SourceRelative(..), sourceRelative,
+
+   -- ** Source Type
+   SourceType(..), sourceType,
+
+   -- ** Buffer Looping
+   LoopingMode(..), loopingMode,
+
+   -- ** Current Buffer
+   buffer,
+
+   -- ** Queue State Queries
+   buffersQueued, buffersProcessed,
+
+   -- ** Bounds on Gain
+   gainBounds,
+
+   -- ** Distance Model Attributes
+   referenceDistance, rolloffFactor, maxDistance,
+
+   -- ** Frequency Shift by Pitch
+   pitch,
+
+   -- ** Direction and Cone
+   -- $DirectionAndCone
+   direction, coneAngles, coneOuterGain,
+
+   -- ** Offset
+   secOffset, sampleOffset, byteOffset,
+
+   -- * Queuing Buffers with a Source
+   -- $QueuingBuffersWithASource
+   queueBuffers, unqueueBuffers,
+
+   -- * Managing Source Execution
+   -- $ManagingSourceExecution
+   SourceState(..), sourceState, play, pause, stop, rewind
+) where
+
+import Control.Monad
+import Foreign.C.Types
+import Foreign.Marshal.Array
+import Foreign.Marshal.Utils
+import Foreign.Ptr
+import Foreign.Storable
+import Graphics.Rendering.OpenGL.GL.ObjectName
+import Graphics.Rendering.OpenGL.GL.StateVar
+import Graphics.Rendering.OpenGL.GL.Tensor
+import Sound.OpenAL.AL.ALboolean
+import Sound.OpenAL.AL.BasicTypes
+import Sound.OpenAL.AL.BufferInternal
+import Sound.OpenAL.AL.Listener
+import Sound.OpenAL.AL.PeekPoke
+import Sound.OpenAL.AL.QueryUtils
+import Sound.OpenAL.AL.SourceState
+import Sound.OpenAL.Constants
+
+-- For Haddock only.
+import Sound.OpenAL.AL.Errors
+
+--------------------------------------------------------------------------------
+
+-- | The abstract buffer type.
+
+newtype Source = Source ALuint
+   deriving ( Eq, Ord, Show )
+
+instance Storable Source where
+   sizeOf    ~(Source b) = sizeOf b
+   alignment ~(Source b) = alignment b
+   peek                  = peek1 Source . castPtr
+   poke ptr   (Source b) = poke1 (castPtr ptr) b
+
+instance ObjectName Source where
+   deleteObjectNames = withArraySizei alDeleteSources
+
+   isObjectName = fmap unmarshalALboolean . alIsSource
+
+instance GeneratableObjectName Source where
+   genObjectNames n =
+      allocaArray n $ \buf -> do
+         alGenSources (fromIntegral n) buf
+         peekArray n buf
+
+foreign import ccall unsafe "alGenSources"
+   alGenSources :: ALsizei -> Ptr Source -> IO ()
+
+foreign import ccall unsafe "alDeleteSources"
+   alDeleteSources :: ALsizei -> Ptr Source -> IO ()
+
+foreign import ccall unsafe "alIsSource"
+   alIsSource :: Source -> IO ALboolean
+
+--------------------------------------------------------------------------------
+
+-- | 'sourcePosition' contains the current location of the source in the world
+-- coordinate system. Any 3-tuple of valid float values is allowed.
+-- Implementation behavior on encountering NaN and infinity is not defined. The
+-- initial position is ('Vertex3' 0 0 0).
+
+sourcePosition :: Source -> StateVar (Vertex3 ALfloat)
+sourcePosition = makeSourceStateVar dictVertex3ALfloat GetPosition
+
+-- | 'sourceVelocity' contains current velocity (speed and direction) of the
+-- source in the world coordinate system. Any 3-tuple of valid float values is
+-- allowed, and the initial velocity is ('Vector3' 0 0 0). 'sourceVelocity' does
+-- not affect 'sourcePosition'. OpenAL does not calculate the velocity from
+-- subsequent position updates, nor does it adjust the position over time based
+-- on the specified velocity. Any such calculation is left to the application.
+-- For the purposes of sound processing, position and velocity are independent
+-- parameters affecting different aspects of the sounds.
+--
+-- 'sourceVelocity' is taken into account by the driver to synthesize the
+-- Doppler effect perceived by the listener for each source, based on the
+-- velocity of both source and listener, and the Doppler related parameters.
+
+sourceVelocity :: Source -> StateVar (Vector3 ALfloat)
+sourceVelocity = makeSourceStateVar dictVector3ALfloat GetVelocity
+
+-- | 'sourceGain' contains a scalar amplitude multiplier for the given source.
+-- The initial value 1 means that the sound is unattenuated. A 'sourceGain'
+-- value of 0.5 is equivalent to an attenuation of 6dB. The value zero equals
+-- silence (no output). Driver implementations are free to optimize this case
+-- and skip mixing and processing stages where applicable. The implementation is
+-- in charge of ensuring artifact-free (click-free) changes of gain values and
+-- is free to defer actual modification of the sound samples, within the limits
+-- of acceptable latencies.
+--
+-- A 'sourceGain' larger than 1 (amplification) is permitted. However, the
+-- implementation is free to clamp the total gain (effective gain per source
+-- times listener gain) to 1 to prevent overflow.
+
+sourceGain :: Source -> StateVar Gain
+sourceGain = makeSourceStateVar dictALfloat GetGain
+
+--------------------------------------------------------------------------------
+
+-- | The entity to which the source attributes 'sourcePosition',
+-- 'sourceVelocity' and 'direction' are to be interpreted.
+
+data SourceRelative =
+     World
+   | Listener
+   deriving ( Eq, Ord, Show )
+
+marshalSourceRelative :: SourceRelative -> Bool
+marshalSourceRelative = (== Listener)
+
+unmarshalSourceRelative :: Bool -> SourceRelative
+unmarshalSourceRelative x = if x then Listener else World
+
+-- | If 'sourceRelative' contains 'Listener', it indicates indicates that the
+-- values specified by 'sourcePosition', 'sourceVelocity' and 'direction' are to
+-- be interpreted relative to the listener position. The initial value is
+-- 'World', indicating that those source attributes are to be interpreted
+-- relative to the world, i.e. they are considered absolute.
+
+sourceRelative :: Source -> StateVar SourceRelative
+sourceRelative = makeSourceStateVar dictSourceRelative GetSourceRelative
+
+--------------------------------------------------------------------------------
+
+-- | When first created, a source will be in the 'Undetermined' state. If a
+-- buffer is then attached using 'buffer', then the source will enter the
+-- 'Static' state. If the first buffer attached to a source is attached using
+-- 'queueBuffers', then the source will enter the 'Streaming' state. A source of
+-- either state will be reset to state 'Undetermined' by setting its 'buffer' to
+-- 'Nothing', and attaching any buffer to a streaming source will change the
+-- state to 'Static'. Attempting to queue a buffer on a static source will
+-- result in an 'ALInvalidOperation' error.
+
+data SourceType =
+     Undetermined
+   | Static
+   | Streaming
+   deriving ( Eq, Ord, Show )
+
+unmarshalSourceType :: ALint -> SourceType
+unmarshalSourceType x
+   | x == al_UNDETERMINED = Undetermined
+   | x == al_STATIC = Static
+   | x == al_STREAMING = Streaming
+   | otherwise = error ("unmarshalSourceType: illegal value " ++ show x)
+
+-- | 'sourceType' indicates whether a source is ready to queue buffers, ready to
+-- use a static buffer, or is in an undetermined state where it can be used for
+-- either streaming or static playback.
+
+sourceType :: Source -> GettableStateVar SourceType
+sourceType = makeSourceGettableStateVar dictSourceType GetSourceType
+
+--------------------------------------------------------------------------------
+
+-- | Specifies what should happen when the end of a buffer queue is reached.
+
+data LoopingMode =
+     OneShot
+   | Looping
+   deriving ( Eq, Ord, Show )
+
+marshalLoopingMode :: LoopingMode -> Bool
+marshalLoopingMode = (== Looping)
+
+unmarshalLoopingMode :: Bool -> LoopingMode
+unmarshalLoopingMode x = if x then Looping else OneShot
+
+-- | If 'loopingMode' contains 'Looping', it indicates that the source will not
+-- be in the 'Stopped' state once it reaches the end of last buffer in the
+-- buffer queue. Instead, the source will immediately promote to 'Initial' and
+-- 'Playing'.  The initial value is 'OneShot'. 'loopingMode' can be changed on a
+-- source in any execution state. In particular, it can be changed on a
+-- 'Playing' source.
+
+loopingMode :: Source -> StateVar LoopingMode
+loopingMode = makeSourceStateVar dictLoopingMode GetLooping
+
+--------------------------------------------------------------------------------
+
+-- | 'buffer' contains the current buffer object. Setting 'buffer' to 'Just' a
+-- buffer object makes it the head entry in the source\'s queue. Setting
+-- 'buffer'for a source in the 'Stopped' or 'Initial' state empties the entire
+-- queue, then appends the one buffer specified (or none at all if 'Nothing'
+-- was specified).
+-- 
+-- For a source in the 'Playing' or 'Paused' state, setting 'buffer' will result
+-- in the 'ALInvalidOperation' error state being set. 'buffer' can be applied only
+-- to sources in the 'Initial' and 'Stopped' states. Specifying an invalid
+-- buffer name (either because the buffer name doesn\'t exist or because that
+-- buffer can\'t be attached to the specified source) will result in an
+-- 'ALInvalidValue' error while specifying an invalid source name results in an
+-- 'ALInvalidName' error. Setting 'buffer' to 'Nothing' is a legal way to release
+-- the current buffer queue on a source in the 'Initial' or 'Stopped' state,
+-- whether the source has just one entry (current buffer) or more. Setting
+-- 'buffer' to 'Nothing' still causes an 'ALInvalidOperation' for any source in
+-- the 'Playing' or 'Paused' state, consequently it cannot be used to mute or
+-- stop a source. The initial value is 'Nothing'.
+
+buffer :: Source -> StateVar (Maybe Buffer)
+buffer = makeSourceStateVar dictMaybeBuffer GetBuffer
+
+--------------------------------------------------------------------------------
+
+-- | 'buffersQueued' contains the number of buffers in the queue of a given
+-- source. This includes those not yet played, the one currently playing, and
+-- the ones that have been played already. It will contain 0 if 'buffer' has
+-- been set to 'Nothing'.
+
+buffersQueued :: Source -> GettableStateVar ALint
+buffersQueued = makeSourceGettableStateVar dictALint GetBuffersQueued
+
+-- | 'buffersProcessed' contains the number of buffers that have been played
+-- by a given source.  Indirectly, this gives the index of the buffer currently
+-- playing. It can be used to determine how much slots are needed for unqueuing
+-- them. On a source in the 'Stopped' state, all buffers are processed. On a
+-- source in the 'Initial' state, no buffers are processed, all buffers are
+-- pending. It will contain 0 if 'buffer' has been set to 'Nothing'.
+
+buffersProcessed :: Source -> GettableStateVar ALint
+buffersProcessed = makeSourceGettableStateVar dictALint GetBuffersProcessed
+
+--------------------------------------------------------------------------------
+
+-- | 'gainBounds' contains two scalar amplitude thresholds between 0 and 1
+-- (included): The minimum guaranteed gain for this source and the maximum gain
+-- permitted, with initial values 0 and 1, respectively At the end of the
+-- processing of various attenuation factors such as distance based attenuation
+-- and 'sourceGain', the effective gain calculated is compared to these values:
+--
+-- If the effective gain is lower than the minimum gain, the minimum gain is
+-- applied. This happens before the 'listenerGain' is applied. If a zero minimum
+-- gain is set, then the effective gain will not be corrected.
+--
+-- If the effective gain is higher than the maximum gain, the maximum gain is
+-- applied. This happens before the 'listenerGain' is applied. If the
+-- 'listenerGain' times the maximum gain still exceeds the maximum gain the
+-- implementation can handle, the implementation is free to clamp. If a zero
+-- maximum gain is set, then the source is effectively muted. The implementation
+-- is free to optimize for this situation, but no optimization is required or
+-- recommended as setting 'sourceGain' to zero is the proper way to mute a
+-- source.
+
+gainBounds :: Source -> StateVar (Gain, Gain)
+gainBounds source =
+   pairStateVars
+      (makeSourceStateVar dictALfloat GetMinGain source)
+      (makeSourceStateVar dictALfloat GetMaxGain source)
+
+--------------------------------------------------------------------------------
+
+-- | 'referenceDistance' is used for distance attenuation calculations based on
+-- inverse distance with rolloff. Depending on the distance model it will also
+-- act as a distance threshold below which gain is clamped. See
+-- "Sound.OpenAL.AL.Attenuation" for details. The initial value is 1.
+
+referenceDistance :: Source -> StateVar ALfloat
+referenceDistance = makeSourceStateVar dictALfloat GetReferenceDistance
+
+-- | 'rolloffFactor' is used for distance attenuation calculations based on
+-- inverse distance with rolloff. For distances smaller than 'maxDistance' (and,
+-- depending on the distance model, larger than 'referenceDistance'), this will
+-- scale the distance attenuation over the applicable range. See
+-- "Sound.OpenAL.AL.Attenuation" for details how the attenuation is computed as
+-- a function of the distance. The initial value is 1.
+-- 
+-- In particular, 'rolloffFactor' can be set to zero for those sources that are
+-- supposed to be exempt from distance attenuation. The implementation is
+-- encouraged to optimize this case, bypassing distance attenuation calculation
+-- entirely on a persource basis.
+
+rolloffFactor :: Source -> StateVar ALfloat
+rolloffFactor = makeSourceStateVar dictALfloat GetRolloffFactor
+
+-- | 'maxDistance' is used for distance attenuation calculations based on
+-- inverse distance with rolloff, if the inverse clamped distance model is
+-- used. In this case, distances greater than 'maxDistance' will be clamped to
+-- 'maxDistance'.  'maxDistance' based clamping is applied before minimum gain
+-- clamping (see 'gainBounds'), so if the effective gain at 'maxDistance' is
+-- larger than the minimum gain, the minimum gain will have no effect. No
+-- culling is supported. The initial value is the largest representable
+-- 'ALfloat'.
+
+maxDistance :: Source -> StateVar ALfloat
+maxDistance = makeSourceStateVar dictALfloat GetMaxDistance
+
+--------------------------------------------------------------------------------
+
+-- | 'pitch' contains the desired pitch shift, where 1 (the initial value)
+-- equals identity. Each reduction by 50 percent equals a pitch shift of -12
+-- semitones (one octave reduction). Each doubling equals a pitch shift of 12
+-- semitones (one octave increase). Zero is not a legal value. Implementations
+-- may clamp the actual output pitch range to any values subject to the
+-- implementation's own limits.
+
+pitch :: Source -> StateVar ALfloat
+pitch = makeSourceStateVar dictALfloat GetPitch
+
+--------------------------------------------------------------------------------
+-- $DirectionAndCone
+-- Each source can be directional, depending on the settings for 'coneAngles'.
+-- There are three zones defined: the inner cone, the outside zone, and the
+-- transitional zone in between. The angle-dependent gain for a directional
+-- source is constant inside the inner cone, and changes over the transitional
+-- zone to the value specified outside the outer cone. 'sourceGain' is applied
+-- for the inner cone, with an application selectable 'coneOuterGain' factor to
+-- define the gain in the outer zone. In the transitional zone
+-- implementation-dependent interpolation between 'sourceGain' and 'sourceGain'
+-- times 'coneOuterGain' is applied.
+
+--------------------------------------------------------------------------------
+
+-- | If 'direction' does not contain the zero vector ('Vector3' 0 0 0), the
+-- source is directional. The sound emission is presumed to be symmetric around
+-- the direction vector (cylinder symmetry). Sources are not oriented in full 3
+-- degrees of freedom, only two angles are effectively needed.
+--
+-- The zero vector is the initial value, indicating that a source is not
+-- directional. Specifying a non-zero vector will make the source directional.
+-- Specifying a zero vector for a directional source will effectively mark it as
+-- nondirectional.
+
+direction :: Source -> StateVar (Vector3 ALfloat)
+direction = makeSourceStateVar dictVector3ALfloat GetDirection
+
+-- | 'coneAngles' contains the inner and outer angles of the sound cone, in
+-- degrees. The default of 360 for the inner cone angle means that it covers the
+-- entire world, which is equivalent to an omni-directional source. The default
+-- of 360 for the outer cone angle means that it covers the entire world. If the
+-- inner angle is also 360, then the zone for angle-dependent attenuation is
+-- zero.
+
+coneAngles :: Source -> StateVar (ALfloat, ALfloat)
+coneAngles source =
+   pairStateVars
+      (makeSourceStateVar dictALfloat GetConeInnerAngle source)
+      (makeSourceStateVar dictALfloat GetConeOuterAngle source)
+
+-- | 'coneOuterGain' contains the factor with which 'sourceGain' is multiplied
+-- to determine the effective gain outside the cone defined by the outer angle.
+-- The effective gain applied outside the outer cone is 'sourceGain' times
+-- 'coneOuterGain'. Changing 'sourceGain' affects all directions, i.e. the
+-- source is attenuated in all directions, for any position of the listener. The
+-- application has to change 'coneOuterGain' as well if a different behavior is
+-- desired.
+
+coneOuterGain :: Source -> StateVar Gain
+coneOuterGain = makeSourceStateVar dictALfloat GetConeOuterGain
+
+--------------------------------------------------------------------------------
+
+-- | 'secOffset' contains the playback position, expressed in seconds (the value
+-- will loop back to zero for looping sources).
+--
+-- When setting 'secOffset' on a source which is already playing, the playback
+-- will jump to the new offset unless the new offset is out of range, in which
+-- case an 'ALInvalidValue' error is set. If the source is not playing, then the
+-- offset will be applied on the next 'play' call.
+--
+-- The position is relative to the beginning of all the queued buffers for the
+-- source, and any queued buffers traversed by a set call will be marked as
+-- processed.
+--
+-- This value is based on byte position, so a pitch-shifted source will have an
+-- exaggerated playback speed. For example, you can be 0.5 seconds into a buffer
+-- having taken only 0.25 seconds to get there if the pitch is set to 2.
+
+secOffset :: Source -> StateVar ALfloat
+secOffset = makeSourceStateVar dictALfloat GetSecOffset
+
+-- | 'sampleOffset' contains the playback position, expressed in samples (the
+-- value will loop back to zero for looping sources). For a compressed format,
+-- this value will represent an exact offset within the uncompressed data.
+-- 
+-- When setting 'sampleOffset' on a source which is already playing, the
+-- playback will jump to the new offset unless the new offset is out of range,
+-- in which case an 'ALInvalidValue' error is set. If the source is not playing,
+-- then the offset will be applied on the next 'play' call. A 'stop', 'rewind',
+-- or a second 'play' call will reset the offset to the beginning of the buffer.
+-- 
+-- The position is relative to the beginning of all the queued buffers for the
+-- source, and any queued buffers traversed by a set call will be marked as
+-- processed.
+
+sampleOffset :: Source -> StateVar ALint
+sampleOffset = makeSourceStateVar dictALint GetSampleOffset
+
+-- | 'byteOffset' contains the playback position, expressed in bytes (the value
+-- will loop back to zero for looping sources). For a compressed format, this
+-- value may represent an approximate offset within the compressed data buffer.
+-- 
+-- When setting 'byteOffset' on a source which is already playing, the playback
+-- will jump to the new offset unless the new offset is out of range, in which
+-- case an 'ALInvalidValue' error is set. If the source is not playing, then the
+-- offset will be applied on the next 'play' call. A 'stop', 'rewind', or a
+-- second 'play' call will reset the offset to the beginning of the buffer.
+-- 
+-- The position is relative to the beginning of all the queued buffers for the
+-- source, and any queued buffers traversed by a set call will be marked as
+-- processed.
+
+byteOffset :: Source -> StateVar ALint
+byteOffset = makeSourceStateVar dictALint GetByteOffset
+
+--------------------------------------------------------------------------------
+
+pairStateVars :: StateVar a -> StateVar b -> StateVar (a,b)
+pairStateVars var1 var2 =
+   makeStateVar
+      (liftM2 (,) (get var1) (get var2))
+      (\(val1,val2) -> do var1 $= val1; var2 $= val2)
+
+data Dictionary a b c = Dictionary {
+   alGetter  :: Source -> ALenum -> Ptr b -> IO (),
+   alSetter  :: Source -> ALenum -> Ptr b -> IO (),
+   size      :: Int,
+   peekSize  :: Ptr b -> IO a,
+   marshal   :: a -> c }
+
+dictALint :: Dictionary ALint ALint ALint
+dictALint = Dictionary {
+   alGetter  = alGetSourceiv,
+   alSetter  = alSourceiv,
+   size      = 1,
+   peekSize  = peek1 id,
+   marshal   = id }
+
+dictALfloat :: Dictionary ALfloat ALfloat ALfloat
+dictALfloat = Dictionary {
+   alGetter  = alGetSourcefv,
+   alSetter  = alSourcefv,
+   size      = 1,
+   peekSize  = peek1 id,
+   marshal   = id }
+
+dictSourceRelative :: Dictionary SourceRelative ALint ALint
+dictSourceRelative = Dictionary {
+   alGetter  = alGetSourceiv,
+   alSetter  = alSourceiv,
+   size      = 1,
+   peekSize  = peek1 (unmarshalSourceRelative . unmarshalALboolean . fromIntegral),
+   marshal   = fromIntegral . marshalALboolean . marshalSourceRelative }
+
+dictSourceType :: Dictionary SourceType ALint ALint
+dictSourceType = Dictionary {
+   alGetter  = alGetSourceiv,
+   alSetter  = undefined,
+   size      = 1,
+   peekSize  = peek1 unmarshalSourceType,
+   marshal   = undefined }
+
+dictLoopingMode :: Dictionary LoopingMode ALint ALint
+dictLoopingMode = Dictionary {
+   alGetter  = alGetSourceiv,
+   alSetter  = alSourceiv,
+   size      = 1,
+   peekSize  = peek1 (unmarshalLoopingMode . unmarshalALboolean . fromIntegral),
+   marshal   = fromIntegral . marshalALboolean . marshalLoopingMode }
+
+dictSourceState :: Dictionary SourceState ALint ALint
+dictSourceState = Dictionary {
+   alGetter  = alGetSourceiv,
+   alSetter  = undefined,
+   size      = 1,
+   peekSize  = peek1 unmarshalSourceState,
+   marshal   = undefined }
+
+dictVertex3ALfloat :: Dictionary (Vertex3 ALfloat) ALfloat (Vertex3 ALfloat)
+dictVertex3ALfloat = Dictionary {
+   alGetter  = alGetSourcefv,
+   alSetter  = alSourcefv,
+   size      = 3,
+   peekSize  = peek3 Vertex3,
+   marshal   = id }
+
+dictVector3ALfloat :: Dictionary (Vector3 ALfloat) ALfloat (Vector3 ALfloat)
+dictVector3ALfloat = Dictionary {
+   alGetter  = alGetSourcefv,
+   alSetter  = alSourcefv,
+   size      = 3,
+   peekSize  = peek3 Vector3,
+   marshal   = id }
+
+dictMaybeBuffer :: Dictionary (Maybe Buffer) ALint ALint
+dictMaybeBuffer = Dictionary {
+   alGetter  = alGetSourceiv,
+   alSetter  = alSourceiv,
+   size      = 1,
+   peekSize  = peek1 (unmarshalBuffer . fromIntegral),
+   marshal   = fromIntegral . marshalBuffer }
+
+makeGetter :: Storable b => Dictionary a b c -> GetPName -> Source -> IO a
+makeGetter dict name source =
+   allocaArray (size dict) $ \buf -> do
+      alGetter dict source (marshalGetPName name) buf
+      peekSize dict buf
+
+makeSetter :: Storable c => Dictionary a b c -> GetPName -> Source -> a -> IO ()
+makeSetter dict name source value =
+   with (marshal dict value) $
+      alSetter dict source (marshalGetPName name) . castPtr
+
+makeSourceStateVar ::
+   (Storable b, Storable c) =>
+   Dictionary a b c -> GetPName -> Source -> StateVar a
+makeSourceStateVar dict name source =
+   makeStateVar
+      (makeGetter dict name source)
+      (makeSetter dict name source)
+
+makeSourceGettableStateVar ::
+   (Storable b, Storable c) =>
+   Dictionary a b c -> GetPName -> Source -> GettableStateVar a
+makeSourceGettableStateVar dict name source =
+   makeGettableStateVar
+      (makeGetter dict name source)
+
+--------------------------------------------------------------------------------
+
+foreign import ccall unsafe "alGetSourcefv"
+   alGetSourcefv :: Source -> ALenum -> Ptr ALfloat -> IO ()
+
+foreign import ccall unsafe "alSourcefv"
+   alSourcefv :: Source -> ALenum -> Ptr ALfloat -> IO ()
+
+foreign import ccall unsafe "alGetSourceiv"
+   alGetSourceiv :: Source ->  ALenum -> Ptr ALint -> IO ()
+
+-- Note: Older OpenAL implementations have no alSourceiv, so we emulate it here.
+alSourceiv :: Source -> ALenum -> Ptr ALint -> IO ()
+alSourceiv source n buf =  peek buf >>= alSourcei source n
+
+foreign import ccall unsafe "alSourcei"
+   alSourcei :: Source -> ALenum -> ALint -> IO ()
+
+--------------------------------------------------------------------------------
+-- $QueuingBuffersWithASource
+-- OpenAL does not specify a built-in streaming mechanism. There is no mechanism
+-- to stream data into a buffer object. Instead, the API has a more flexible and
+-- versatile mechanism to queue buffers for sources. There are many ways to use
+-- this feature, with streaming being only one of them.
+--
+-- Streaming is replaced by queuing static buffers. This effectively moves any
+-- multi-buffer caching into the application and allows the application to
+-- select how many buffers it wants to use, the size of the buffers, and whether
+-- these are re-used in cycle, pooled, or thrown away.
+--
+-- Looping (over a finite number of repetitions) can be implemented by
+-- explicitly repeating buffers in the queue. Infinite loops can (theoretically)
+-- be accomplished by sufficiently large repetition counters. If only a single
+-- buffer is supposed to be repeated infinitely, using the respective source
+-- attribute 'loopingMode' is recommended.
+--
+-- Loop Points for restricted looping inside a buffer can in many cases be
+-- replaced by splitting the sample into several buffers and queuing the sample
+-- fragments (including repetitions) accordingly.
+--
+-- Buffers can be queued, unqueued after they have been used, and either be
+-- deleted, or refilled and queued again. Splitting large samples over several
+-- buffers maintained in a queue has distinct advantages over approaches that
+-- require explicit management of samples and sample indices.
+
+--------------------------------------------------------------------------------
+
+-- | The application can queue up one or multiple buffer names using
+-- 'queueBuffers'. The buffers will be queued in the sequence in which they
+-- appear in the list.
+--
+-- This command is legal on a source in any playback state (to allow for
+-- streaming, queuing has to be possible on a 'Playing' source).
+--
+-- All buffers in a queue must have the same format and attributes. An attempt
+-- to mix formats or other buffer attributes will result in a failure and an
+-- 'ALInvalidValue' error will be thrown. If the queue operation fails, the source
+-- queue will remain unchanged (even if some of the buffers could have been
+-- queued).
+
+queueBuffers :: Source -> [Buffer] -> IO ()
+queueBuffers = withArraySizei . alSourceQueueBuffers
+
+withArraySizei :: Storable a => (ALsizei -> Ptr a -> IO ()) -> [a] -> IO ()
+withArraySizei f xs = withArrayLen xs $ f . fromIntegral
+
+foreign import ccall unsafe "alSourceQueueBuffers"
+   alSourceQueueBuffers :: Source -> ALsizei -> Ptr Buffer -> IO ()
+
+--------------------------------------------------------------------------------
+
+-- | Once a queue entry for a buffer has been appended to a queue and is pending
+-- processing, it should not be changed. Removal of a given queue entry is not
+-- possible unless either the source is stopped (in which case then entire queue
+-- is considered processed), or if the queue entry has already been processed
+-- ('Playing' or 'Paused' source). A playing source will enter the 'Stopped'
+-- state if it completes playback of the last buffer in its queue (the same
+-- behavior as when a single buffer has been attached to a source and has
+-- finished playback).
+--
+-- The 'unqueueBuffers' command removes a number of buffers entries that have
+-- finished processing from the queue, returning the buffers that were unqueued.
+-- The operation will fail with an 'ALInvalidValue' error if more buffers are
+-- requested than available, leaving the destination arguments unchanged.
+
+unqueueBuffers :: Source -> ALsizei -> IO [Buffer]
+unqueueBuffers src n = allocaArray (fromIntegral n) $ \p -> do
+    alSourceUnqueueBuffers src n p
+    peekArray (fromIntegral n) p
+
+foreign import ccall unsafe "alSourceUnqueueBuffers"
+   alSourceUnqueueBuffers :: Source -> ALsizei -> Ptr Buffer -> IO ()
+
+--------------------------------------------------------------------------------
+-- $ManagingSourceExecution
+-- The execution state of a source can be queried. OpenAL provides a set of
+-- functions that initiate state transitions causing sources to start and stop
+-- execution.
+
+--------------------------------------------------------------------------------
+
+-- | Contains the current execution state of the given source. The initial state
+-- of any source is 'Initial'.
+--
+-- Note that the 'Initial' state is not necessarily identical to the initial
+-- state in which a source is created, because the other source attributes are
+-- not automatically reset to their initial values. 'Initial' merely indicates
+-- that the source can be executed using the 'play' command. A 'Stopped' or
+-- 'Initial' source can be reset into the default configuration by using a
+-- sequence of source commands as necessary. As the application has to specify
+-- all relevant state anyway to create a useful source configuration, no reset
+-- command is provided.
+
+sourceState :: Source -> GettableStateVar SourceState
+sourceState source =
+   makeGettableStateVar
+      (makeGetter dictSourceState GetSourceState source)
+
+--------------------------------------------------------------------------------
+
+-- | 'play' applied to an 'Initial' source will promote the source to 'Playing',
+-- thus the data found in the buffer will be fed into the processing, starting
+-- at the beginning. 'play' applied to a 'Playing' source will restart the
+-- source from the beginning. It will not affect the configuration, and will
+-- leave the source in 'Playing' state, but reset the sampling offset to the
+-- beginning. 'play' applied to a 'Paused' source will resume processing using
+-- the source state as preserved at the 'pause' operation. 'play' applied to a
+-- 'Stopped' source will propagate it to 'Initial' then to 'Playing'
+-- immediately.
+
+play :: [Source] -> IO ()
+play = withArraySizei alSourcePlayv
+
+foreign import ccall unsafe "alSourcePlayv"
+   alSourcePlayv :: ALsizei -> Ptr Source -> IO ()
+
+-- | 'pause' applied to an 'Initial' source is a legal NOP. 'pause' applied to a
+-- 'Playing' source will change its state to 'Paused'. The source is exempt from
+-- processing, its current state is preserved. 'pause' applied to a 'Paused'
+-- source is a legal NOP. 'pause' applied to a 'Stopped' source is a legal NOP.
+
+pause :: [Source] -> IO ()
+pause = withArraySizei alSourcePausev
+
+foreign import ccall unsafe "alSourcePausev"
+   alSourcePausev :: ALsizei -> Ptr Source -> IO ()
+
+-- | 'stop' applied to an 'Initial' source is a legal NOP. 'stop' applied to a
+-- 'Playing' source will change its state to 'Stopped'. The source is exempt
+-- from processing, its current state is preserved. 'stop' applied to a 'Paused'
+-- source will change its state to 'Stopped', with the same consequences as on a
+-- 'Playing' source. 'stop' applied to a 'Stopped' source is a legal NOP.
+
+stop :: [Source] -> IO ()
+stop = withArraySizei alSourceStopv
+
+foreign import ccall unsafe "alSourceStopv"
+   alSourceStopv :: ALsizei -> Ptr Source -> IO ()
+
+-- | 'rewind' applied to an 'Initial' source is a legal NOP. 'rewind' applied to
+-- a 'Playing' source will change its state to 'Stopped' then 'Initial'. The
+-- source is exempt from processing: its current state is preserved, with the
+-- exception of the sampling offset, which is reset to the beginning.  'rewind'
+-- applied to a 'Paused' source will change its state to 'Initial', with the
+-- same consequences as on a 'Playing' source.  'rewind' applied to an 'Stopped'
+-- source promotes the source to 'Initial', resetting the sampling offset to the
+-- beginning.
+
+rewind :: [Source] -> IO ()
+rewind = withArraySizei alSourceRewindv
+
+foreign import ccall unsafe "alSourceRewindv"
+   alSourceRewindv :: ALsizei -> Ptr Source -> IO ()
diff --git a/src/Sound/OpenAL/AL/SourceState.hs b/src/Sound/OpenAL/AL/SourceState.hs
new file mode 100644
--- /dev/null
+++ b/src/Sound/OpenAL/AL/SourceState.hs
@@ -0,0 +1,46 @@
+{-# OPTIONS_HADDOCK hide #-}
+--------------------------------------------------------------------------------
+-- |
+-- Module      :  Sound.OpenAL.AL.SourceState
+-- Copyright   :  (c) Sven Panne 2003-2013
+-- License     :  BSD3
+-- 
+-- Maintainer  :  Sven Panne <svenpanne@gmail.com>
+-- Stability   :  stable
+-- Portability :  portable
+--
+--------------------------------------------------------------------------------
+
+module Sound.OpenAL.AL.SourceState (
+   SourceState(..), unmarshalSourceState
+) where
+
+import Sound.OpenAL.AL.BasicTypes ( ALint )
+import Sound.OpenAL.Constants ( al_INITIAL, al_PLAYING, al_PAUSED, al_STOPPED )
+
+--------------------------------------------------------------------------------
+
+-- | Each source can be in one of four possible execution states: 'Initial',
+-- 'Playing', 'Paused', 'Stopped'. Sources that are either 'Playing' or 'Paused'
+-- are considered active. Sources that are 'Stopped' or 'Initial' are considered
+-- inactive. Only 'Playing' sources are included in the processing. The
+-- implementation is free to skip those processing stages for sources that have
+-- no effect on the output (e.g. mixing for a source muted by zero gain, but not
+-- sample offset increments). Depending on the current state of a source certain
+-- (e.g. repeated) state transition commands are legal NOPs: they will be
+-- ignored, no error is generated.
+
+data SourceState =
+     Initial
+   | Playing
+   | Paused
+   | Stopped
+   deriving ( Eq, Ord, Show )
+
+unmarshalSourceState :: ALint -> SourceState
+unmarshalSourceState x
+   | x == al_INITIAL = Initial
+   | x == al_PLAYING = Playing
+   | x == al_PAUSED = Paused
+   | x == al_STOPPED = Stopped
+   | otherwise = error ("unmarshalSourceState: illegal value " ++ show x)
diff --git a/src/Sound/OpenAL/AL/String.hs b/src/Sound/OpenAL/AL/String.hs
new file mode 100644
--- /dev/null
+++ b/src/Sound/OpenAL/AL/String.hs
@@ -0,0 +1,31 @@
+{-# OPTIONS_HADDOCK hide #-}
+--------------------------------------------------------------------------------
+-- |
+-- Module      :  Sound.OpenAL.AL.String
+-- Copyright   :  (c) Sven Panne 2003-2013
+-- License     :  BSD3
+-- 
+-- Maintainer  :  Sven Panne <svenpanne@gmail.com>
+-- Stability   :  stable
+-- Portability :  portable
+--
+--------------------------------------------------------------------------------
+
+module Sound.OpenAL.AL.String (
+   withALString, peekALString
+) where
+
+import Foreign.C.String ( withCString, peekCString )
+import Foreign.Ptr ( Ptr, castPtr )
+import Sound.OpenAL.AL.BasicTypes ( ALchar )
+
+--------------------------------------------------------------------------------
+
+-- AL uses "Ptr ALchar" instead of "CString" for strings, so some wrappers
+-- are quite handy.
+
+withALString :: String -> (Ptr ALchar -> IO a) -> IO a
+withALString str action = withCString str (action . castPtr)
+
+peekALString :: Ptr ALchar -> IO String
+peekALString = peekCString . castPtr
diff --git a/src/Sound/OpenAL/AL/StringQueries.hs b/src/Sound/OpenAL/AL/StringQueries.hs
new file mode 100644
--- /dev/null
+++ b/src/Sound/OpenAL/AL/StringQueries.hs
@@ -0,0 +1,33 @@
+--------------------------------------------------------------------------------
+-- |
+-- Module      :  Sound.OpenAL.AL.StringQueries
+-- Copyright   :  (c) Sven Panne 2003-2013
+-- License     :  BSD3
+-- 
+-- Maintainer  :  Sven Panne <svenpanne@gmail.com>
+-- Stability   :  stable
+-- Portability :  portable
+--
+-- This module corresponds to section 3.1.2 (String Queries) of the OpenAL
+-- Specification and Reference (version 1.1).
+--
+--------------------------------------------------------------------------------
+
+module Sound.OpenAL.AL.StringQueries (
+   alVendor, alRenderer
+) where
+
+import Graphics.Rendering.OpenGL.GL.StateVar
+import Sound.OpenAL.AL.QueryUtils ( StringName(..), getString )
+
+--------------------------------------------------------------------------------
+
+-- | Contains the name of the vendor.
+
+alVendor :: GettableStateVar String
+alVendor = makeGettableStateVar (getString Vendor)
+
+-- | Contains information about the specific renderer.
+
+alRenderer :: GettableStateVar String
+alRenderer = makeGettableStateVar (getString Renderer)
diff --git a/src/Sound/OpenAL/ALC.hs b/src/Sound/OpenAL/ALC.hs
new file mode 100644
--- /dev/null
+++ b/src/Sound/OpenAL/ALC.hs
@@ -0,0 +1,35 @@
+--------------------------------------------------------------------------------
+-- |
+-- Module      :  Sound.OpenAL.ALC
+-- Copyright   :  (c) Sven Panne 2003-2013
+-- License     :  BSD3
+-- 
+-- Maintainer  :  Sven Panne <svenpanne@gmail.com>
+-- Stability   :  stable
+-- Portability :  portable
+--
+-- This module corresponds to chapter 6 (AL Contexts and the ALC API) of the
+-- OpenAL Specification and Reference (version 1.1).
+--
+-- ALC is a portable API for managing OpenAL contexts, including resource
+-- sharing, locking, and unlocking. Within the core AL API the existence of a
+-- context is implied, but the context is not exposed. The context encapsulates
+-- the state of a given instance of the AL state machine.
+--
+--------------------------------------------------------------------------------
+
+module Sound.OpenAL.ALC (
+   module Sound.OpenAL.ALC.BasicTypes,
+   module Sound.OpenAL.ALC.Device,
+   module Sound.OpenAL.ALC.Context,
+   module Sound.OpenAL.ALC.Extensions,
+   module Sound.OpenAL.ALC.Errors,
+   module Sound.OpenAL.ALC.Capture
+) where
+
+import Sound.OpenAL.ALC.BasicTypes
+import Sound.OpenAL.ALC.Device
+import Sound.OpenAL.ALC.Context
+import Sound.OpenAL.ALC.Extensions
+import Sound.OpenAL.ALC.Errors
+import Sound.OpenAL.ALC.Capture
diff --git a/src/Sound/OpenAL/ALC/ALCboolean.hs b/src/Sound/OpenAL/ALC/ALCboolean.hs
new file mode 100644
--- /dev/null
+++ b/src/Sound/OpenAL/ALC/ALCboolean.hs
@@ -0,0 +1,30 @@
+{-# OPTIONS_HADDOCK hide #-}
+--------------------------------------------------------------------------------
+-- |
+-- Module      :  Sound.OpenAL.ALC.ALCboolean
+-- Copyright   :  (c) Sven Panne 2003-2013
+-- License     :  BSD3
+-- 
+-- Maintainer  :  Sven Panne <svenpanne@gmail.com>
+-- Stability   :  stable
+-- Portability :  portable
+--
+-- This is a purely internal module for (un-)marshaling ALCboolean.
+--
+--------------------------------------------------------------------------------
+
+module Sound.OpenAL.ALC.ALCboolean (
+   marshalALCboolean, unmarshalALCboolean
+) where
+
+import Sound.OpenAL.ALC.BasicTypes ( ALCboolean )
+import Sound.OpenAL.Constants ( alc_FALSE, alc_TRUE )
+
+--------------------------------------------------------------------------------
+
+marshalALCboolean :: Bool -> ALCboolean
+marshalALCboolean False = alc_FALSE
+marshalALCboolean True  = alc_TRUE
+
+unmarshalALCboolean :: ALCboolean -> Bool
+unmarshalALCboolean = (/= alc_FALSE)
diff --git a/src/Sound/OpenAL/ALC/BasicTypes.hs b/src/Sound/OpenAL/ALC/BasicTypes.hs
new file mode 100644
--- /dev/null
+++ b/src/Sound/OpenAL/ALC/BasicTypes.hs
@@ -0,0 +1,24 @@
+--------------------------------------------------------------------------------
+-- |
+-- Module      :  Sound.OpenAL.ALC.BasicTypes
+-- Copyright   :  (c) Sven Panne 2003-2013
+-- License     :  BSD3
+-- 
+-- Maintainer  :  Sven Panne <svenpanne@gmail.com>
+-- Stability   :  stable
+-- Portability :  portable
+--
+-- This module corresponds to the introductory parts of chapter 6 (AL Contexts
+-- and the ALC API) of the OpenAL Specification and Reference (version 1.1).
+--
+-- The context API makes use of ALC types which are defined separately from the
+-- AL types - there is an 'ALCboolean', 'ALCchar', etc.
+--
+--------------------------------------------------------------------------------
+
+module Sound.OpenAL.ALC.BasicTypes (
+   ALCboolean, ALCchar, ALCbyte, ALCubyte, ALCshort, ALCushort, ALCint, ALCuint,
+   ALCsizei, ALCenum, ALCfloat, ALCdouble
+) where
+
+import Sound.OpenAL.Config
diff --git a/src/Sound/OpenAL/ALC/Capture.hs b/src/Sound/OpenAL/ALC/Capture.hs
new file mode 100644
--- /dev/null
+++ b/src/Sound/OpenAL/ALC/Capture.hs
@@ -0,0 +1,138 @@
+--------------------------------------------------------------------------------
+-- |
+-- Module      :  Sound.OpenAL.ALC.Capture
+-- Copyright   :  (c) Sven Panne 2003-2013
+-- License     :  BSD3
+-- 
+-- Maintainer  :  Sven Panne <svenpanne@gmail.com>
+-- Stability   :  stable
+-- Portability :  portable
+--
+-- This module corresponds to section 6.4.2. (Capture) of the OpenAL
+-- Specification and Reference (version 1.1).
+--
+--------------------------------------------------------------------------------
+
+module Sound.OpenAL.ALC.Capture (
+   NumSamples, captureOpenDevice, captureStart, captureNumSamples,
+   captureSamples, captureStop, captureCloseDevice,
+   captureDefaultDeviceSpecifier, captureDeviceSpecifier,
+   allCaptureDeviceSpecifiers
+) where
+
+import Graphics.Rendering.OpenGL.GL.StateVar
+import Foreign.C.Types
+import Foreign.Ptr ( Ptr, nullPtr, FunPtr )
+import Sound.OpenAL.AL.Buffer ( Format )
+import Sound.OpenAL.AL.Format ( marshalFormat )
+import Sound.OpenAL.ALC.ALCboolean ( unmarshalALCboolean )
+import Sound.OpenAL.ALC.BasicTypes (
+   ALCchar, ALCuint, ALCenum, ALCsizei, ALCboolean )
+import Sound.OpenAL.ALC.Context ( Frequency )
+import Sound.OpenAL.ALC.Device ( Device )
+import Sound.OpenAL.ALC.Extensions ( alcProcAddress )
+import Sound.OpenAL.ALC.QueryUtils ( IntQuery(..), getInteger )
+import Sound.OpenAL.ALC.QueryUtils (
+   StringQuery(..), getString, getStringRaw, alcIsExtensionPresent )
+import Sound.OpenAL.ALC.String ( withALCString, peekALCStrings )
+import Sound.OpenAL.Config ( ALCdevice(..), marshalDevice, unmarshalDevice )
+
+--------------------------------------------------------------------------------
+
+type NumSamples = ALCsizei
+
+--------------------------------------------------------------------------------
+
+type Invoker a = FunPtr a -> a
+
+getCaptureFunc :: String -> IO (FunPtr a)
+getCaptureFunc = get . alcProcAddress Nothing
+
+--------------------------------------------------------------------------------
+
+captureOpenDevice ::
+   Maybe String -> Frequency -> Format -> NumSamples -> IO (Maybe Device)
+captureOpenDevice maybeDeviceSpec frequency format size = do
+   funPtr <- getCaptureFunc "alcCaptureOpenDevice"
+   let open deviceSpec =
+          invokeCaptureOpenDevice funPtr deviceSpec (round frequency)
+                                  (fromIntegral (marshalFormat format)) size
+   fmap unmarshalDevice $
+      (maybe (open nullPtr)   -- use preferred device
+             (flip withALCString open)
+             maybeDeviceSpec)
+
+foreign import ccall unsafe "dynamic"
+   invokeCaptureOpenDevice :: Invoker (Ptr ALCchar -> ALCuint -> ALCenum -> ALCsizei -> IO ALCdevice)
+
+--------------------------------------------------------------------------------
+
+captureStart :: Device -> IO ()
+captureStart = captureStartStop "alcCaptureStart"
+
+captureStartStop :: String -> Device -> IO ()
+captureStartStop funName device = do
+   funPtr <- getCaptureFunc funName
+   invokeCaptureStartStop funPtr (marshalDevice device)
+
+foreign import ccall unsafe "dynamic"
+   invokeCaptureStartStop :: Invoker (ALCdevice -> IO ()) 
+
+--------------------------------------------------------------------------------
+
+captureNumSamples :: Device -> GettableStateVar NumSamples
+captureNumSamples device = makeGettableStateVar $
+   fmap fromIntegral (getInteger (Just device) CaptureSamples)
+
+--------------------------------------------------------------------------------
+
+captureSamples :: Device -> Ptr a -> NumSamples -> IO ()
+captureSamples device buf n = do
+   funPtr <- getCaptureFunc "alcCaptureSamples"
+   invokeCaptureSamples funPtr (marshalDevice device) buf n
+
+foreign import ccall unsafe "dynamic"
+   invokeCaptureSamples :: Invoker (ALCdevice -> Ptr a -> NumSamples -> IO ())
+
+--------------------------------------------------------------------------------
+
+captureStop :: Device -> IO ()
+captureStop = captureStartStop "alcCaptureStop"
+
+--------------------------------------------------------------------------------
+
+captureCloseDevice :: Device -> IO Bool
+captureCloseDevice device = do
+   funPtr <- getCaptureFunc "alcCaptureCloseDevice"
+   fmap unmarshalALCboolean .
+      invokeCaptureCloseDevice funPtr . marshalDevice $ device
+
+foreign import ccall unsafe "dynamic"
+   invokeCaptureCloseDevice :: Invoker (ALCdevice -> IO ALCboolean) 
+
+--------------------------------------------------------------------------------
+
+-- | Contains the name of the default capture device.
+
+captureDefaultDeviceSpecifier :: GettableStateVar String
+captureDefaultDeviceSpecifier = makeGettableStateVar $
+   getString Nothing CaptureDefaultDeviceSpecifier
+
+--------------------------------------------------------------------------------
+
+-- | Contains the specifier string for the given capture device.
+
+captureDeviceSpecifier :: Device -> GettableStateVar String
+captureDeviceSpecifier device = makeGettableStateVar $
+   getString (Just device) CaptureDeviceSpecifier
+
+--------------------------------------------------------------------------------
+
+-- | Contains a list of specifiers for all available capture devices.
+
+allCaptureDeviceSpecifiers :: GettableStateVar [String]
+allCaptureDeviceSpecifiers = makeGettableStateVar $ do
+   enumExtPresent <- get (alcIsExtensionPresent Nothing "ALC_ENUMERATION_EXT")
+   if enumExtPresent
+      then peekALCStrings =<< getStringRaw Nothing CaptureDeviceSpecifier
+      else fmap (\s -> [s]) $ get captureDefaultDeviceSpecifier
diff --git a/src/Sound/OpenAL/ALC/Context.hs b/src/Sound/OpenAL/ALC/Context.hs
new file mode 100644
--- /dev/null
+++ b/src/Sound/OpenAL/ALC/Context.hs
@@ -0,0 +1,194 @@
+{-# OPTIONS_GHC -fno-warn-unused-imports #-}
+--------------------------------------------------------------------------------
+-- |
+-- Module      :  Sound.OpenAL.ALC.Context
+-- Copyright   :  (c) Sven Panne 2003-2013
+-- License     :  BSD3
+-- 
+-- Maintainer  :  Sven Panne <svenpanne@gmail.com>
+-- Stability   :  stable
+-- Portability :  portable
+--
+-- This module corresponds to section 6.2 (Managing Rendering Contexts) of the
+-- OpenAL Specification and Reference (version 1.1).
+--
+-- All operations of the AL core API affect a current AL context. Within the
+-- scope of AL, the ALC is implied - it is not visible as a handle or function
+-- parameter. Only one AL Context per process can be current at a time.
+-- Applications maintaining multiple AL Contexts, whether threaded or not,
+-- have to set the current context accordingly. Applications can have multiple
+-- threads that share one more or contexts. In other words, AL and ALC are
+-- threadsafe.
+--
+--------------------------------------------------------------------------------
+
+module Sound.OpenAL.ALC.Context (
+   Frequency, ContextAttribute(..), Context, createContext, currentContext,
+   processContext, suspendContext, destroyContext, contextsDevice, allAttributes
+) where
+
+import Foreign.Marshal.Array
+import Foreign.Ptr
+import Graphics.Rendering.OpenGL.GL.StateVar
+import Sound.OpenAL.ALC.ALCboolean
+import Sound.OpenAL.ALC.BasicTypes
+import Sound.OpenAL.ALC.Device
+import Sound.OpenAL.ALC.QueryUtils
+import Sound.OpenAL.Config
+import Sound.OpenAL.Constants
+
+-- For Haddock only.
+import Sound.OpenAL.ALC.Errors
+
+--------------------------------------------------------------------------------
+
+-- | Frequency, specified in samples per second, i.e. units of Hertz \[Hz\].
+-- Note that the underlying OpenAL API currently uses integral frequencies
+-- only, but we want to mirror physical reality here more closely.
+
+type Frequency = Float
+
+--------------------------------------------------------------------------------
+
+-- | The application can choose to specify certain attributes for a context at
+-- context-creation time. Attributes not specified explicitly are set to
+-- implementation dependent defaults.
+
+data ContextAttribute =
+     Frequency Frequency   -- ^ Frequency for mixing output buffer, in units of
+                           --   Hz
+   | Refresh Frequency     -- ^ Refresh intervals, in units of Hz
+   | Sync Bool             -- ^ Flag, indicating a synchronous context
+   | MonoSources Int       -- ^ A hint indicating how many sources should be
+                           --   capable of supporting mono data
+   | StereoSources Int     -- ^ A hint indicating how many sources should be
+                           --   capable of supporting stereo data
+   deriving ( Eq, Ord, Show )
+
+marshalContextAttribute :: ContextAttribute -> (ALCint,ALCint)
+marshalContextAttribute a = case a of
+   Frequency f -> (alc_FREQUENCY, round f)
+   Refresh r -> (alc_REFRESH, round r)
+   Sync s -> (alc_SYNC, fromIntegral (marshalALCboolean s))
+   MonoSources m -> (alc_MONO_SOURCES, fromIntegral m)
+   StereoSources s -> (alc_STEREO_SOURCES, fromIntegral s)
+
+unmarshalContextAttribute :: (ALCint,ALCint) -> ContextAttribute
+unmarshalContextAttribute a@(x,y)
+   | x == alc_FREQUENCY = Frequency (fromIntegral y)
+   | x == alc_REFRESH = Refresh (fromIntegral y)
+   | x == alc_SYNC = Sync (unmarshalALCboolean (fromIntegral y))
+   | x == alc_MONO_SOURCES = MonoSources (fromIntegral y)
+   | x == alc_STEREO_SOURCES = StereoSources (fromIntegral y)
+   | otherwise = error ("unmarshalContextAttribute: illegal value " ++ show a)
+
+--------------------------------------------------------------------------------
+
+-- | Create a context for a given device and given attributes. Context creation
+-- will fail in the following cases: a) if the application requests attributes
+-- that, by themselves, can not be provided b) if the combination of specified
+-- attributes can not be provided c) if a specified attribute, or the
+-- combination of attributes, does not match the default values for unspecified
+-- attributes If context creation fails, 'Nothing' will be returned, otherwise
+-- 'Just' the new context. Note that 'createContext' does /not/ set the current
+-- context, this must be done separately via 'currentContext'.
+
+createContext :: Device -> [ContextAttribute] -> IO (Maybe Context)
+createContext device attributes = do
+   let pairToList (key, value) = [key, value]
+       attrs = concatMap (pairToList . marshalContextAttribute) attributes
+   fmap unmarshalContext .
+      withArray0 0 attrs . alcCreateContext . marshalDevice $ device
+
+foreign import ccall unsafe "alcCreateContext"
+   alcCreateContext :: ALCdevice -> Ptr ALCint -> IO ALCcontext
+
+--------------------------------------------------------------------------------
+
+-- | Contains 'Just' the current context with respect to OpenAL operation, or
+-- 'Nothing' if there is no current context. Setting it to the latter is useful
+-- when shutting OpenAL down. The state variable applies to the device that the
+-- context was created for. For each OS process (usually this means for each
+-- application), only one context can be current at any given time. All AL
+-- commands apply to the current context. Commands that affect objects shared
+-- among contexts (e.g. buffers) have side effects on other contexts.
+
+currentContext :: StateVar (Maybe Context)
+currentContext = makeStateVar getCurrentContext makeContextCurrent
+
+getCurrentContext :: IO (Maybe Context)
+getCurrentContext = fmap unmarshalContext $ alcGetCurrentContext
+
+foreign import ccall unsafe "alcGetCurrentContext"
+   alcGetCurrentContext :: IO ALCcontext
+
+makeContextCurrent :: Maybe Context -> IO ()
+makeContextCurrent =
+   fmap (const ()) . alcMakeContextCurrent . marshalContext . maybe nullContext id
+
+--------------------------------------------------------------------------------
+
+-- | The current context is the only context accessible to state changes by AL
+-- commands (aside from state changes affecting shared objects). However,
+-- multiple contexts can be processed at the same time. To indicate that a
+-- context should be processed (i.e. that internal execution state like offset
+-- increments are supposed to be performed), the application has to use
+-- 'processContext'. Repeated calls to 'processContext' are legal, and do not
+-- affect a context that is already marked as processing. The default state of a
+-- context created by 'createContext' is that it is processing.
+
+processContext :: Context -> IO ()
+processContext = fmap (const ()) . alcProcessContext . marshalContext
+
+-- | The application can suspend any context from processing (including the
+-- current one). To indicate that a context should be suspended from processing
+-- (i.e. that internal execution state like offset increments is not supposed to
+-- be changed), the application has to use 'suspendContext'. Repeated calls to
+-- 'suspendContext' are legal, and do not affect a context that is already
+-- marked as suspended.
+
+suspendContext :: Context -> IO ()
+suspendContext = alcSuspendContext . marshalContext
+
+foreign import ccall unsafe "alcSuspendContext"
+   alcSuspendContext :: ALCcontext -> IO ()
+
+--------------------------------------------------------------------------------
+
+-- | Destroy the given context. Note that the the correct way to destroy a
+-- context is to first release it by setting 'currentContext' to
+-- 'Nothing'. Applications should not attempt to destroy a current context,
+-- doing so will not work and will result in an 'ALCInvalidOperation' error.
+
+destroyContext :: Context -> IO ()
+destroyContext = fmap (const ()) . alcDestroyContext . marshalContext
+
+--------------------------------------------------------------------------------
+
+-- | Contains 'Just' the device of the given context or 'Nothing' if the context
+-- is invalid.
+
+contextsDevice :: Context -> GettableStateVar (Maybe Device)
+contextsDevice =
+   makeGettableStateVar .
+      fmap unmarshalDevice . alcGetContextsDevice . marshalContext
+
+foreign import ccall unsafe "alcGetContextsDevice"
+   alcGetContextsDevice :: ALCcontext -> IO ALCdevice
+
+--------------------------------------------------------------------------------
+
+-- | Contains the attribute list for the current context of the specified
+-- device.
+
+allAttributes :: Device -> GettableStateVar [ContextAttribute]
+allAttributes device = makeGettableStateVar $ do
+   numALCints <- fmap fromIntegral $ getInteger (Just device) AttributesSize
+   fmap toContextAttributes $ getIntegerv (Just device) AllAttributes numALCints
+
+toContextAttributes :: [ALCint] -> [ContextAttribute]
+toContextAttributes xs = case xs of
+   [] -> []  -- should only happen when device and/or current context is invalid
+   (0:_) -> []
+   (x:y:rest) -> unmarshalContextAttribute (x,y) : toContextAttributes rest
+   _ -> error ("toContextAttributes: illegal value " ++ show xs)
diff --git a/src/Sound/OpenAL/ALC/Device.hs b/src/Sound/OpenAL/ALC/Device.hs
new file mode 100644
--- /dev/null
+++ b/src/Sound/OpenAL/ALC/Device.hs
@@ -0,0 +1,222 @@
+--------------------------------------------------------------------------------
+-- |
+-- Module      :  Sound.OpenAL.ALC.Device
+-- Copyright   :  (c) Sven Panne 2003-2013
+-- License     :  BSD3
+-- 
+-- Maintainer  :  Sven Panne <svenpanne@gmail.com>
+-- Stability   :  stable
+-- Portability :  portable
+--
+-- This module corresponds to section 6.1 (Managing Devices) of the OpenAL
+-- Specification and Reference (version 1.1).
+--
+-- ALC introduces the notion of a device. A device can be, depending on the
+-- implementation, a hardware device, or a daemon\/OS service\/actual
+-- server. This mechanism also permits different drivers (and hardware) to
+-- coexist within the same system, as well as allowing several applications to
+-- share system resources for audio, including a single hardware output
+-- device. The details are left to the implementation, which has to map the
+-- available backends to unique device specifiers.
+--
+--------------------------------------------------------------------------------
+
+module Sound.OpenAL.ALC.Device (
+   Device, openDevice, closeDevice,
+   defaultDeviceSpecifier, deviceSpecifier, allDeviceSpecifiers
+) where
+
+import Graphics.Rendering.OpenGL.GL.StateVar
+import Foreign.Ptr ( Ptr, nullPtr )
+import Foreign.Marshal.Utils ( maybePeek )
+import Sound.OpenAL.ALC.BasicTypes ( ALCchar )
+import Sound.OpenAL.ALC.QueryUtils (
+   StringQuery(..), getString, getStringRaw, alcIsExtensionPresent )
+import Sound.OpenAL.ALC.String ( withALCString, peekALCString, peekALCStrings )
+import Sound.OpenAL.Config (
+   Device, ALCdevice(..), unmarshalDevice, closeDevice )
+
+--------------------------------------------------------------------------------
+
+-- | 'openDevice' allows the application (i.e. the client program) to connect to
+-- a device (i.e. the server). If the function returns 'Nothing', then no sound
+-- driver\/device has been found. The argument to 'openDevice' specifies a
+-- certain device or device configuration. If it is 'Nothing', the
+-- implementation will provide an implementation specific default, see
+-- 'defaultDeviceSpecifier'. Otherwise it is 'Just' an implementation-dependent
+-- string. You can use 'allDeviceSpecifiers' to get a list of the known OpenAL
+-- devices.
+--
+-- /Notes for Windows:/ There are 3 possible device strings, each having a
+-- deprecated equivalent for legacy applications only:
+--
+-- * @\"Generic Hardware\"@ (legacy string: @\"DirectSound3D\"@)
+--
+-- * @\"Generic Software\"@ (legacy string: @\"DirectSound\"@)
+--
+-- * @\"Generic Software Fallback\"@ (legacy string: @\"MMSYSTEM\"@)
+--
+-- /Notes for Linux\/\*nix:/ If an @.openalrc@ file is present in the user\'s
+-- home directory, it is loaded first, otherwise @\/etc\/openalrc@ is tried.
+-- The bindings (if any) of @devices@, @direction@, @sampling-rate@, and
+-- @speaker-num@ (see below) after loading one of these files take precedence
+-- over any bindings done via the argument to 'openDevice'.
+--
+-- The syntax of these files is lisp-based and a sequence of expressions, where
+-- an expression is one the following:
+--
+-- * A boolean value of the form @\#f@ or @\#t@, which evaluate to /false/ and
+-- /true/, respectively.
+--
+-- * An non-negative integer value, i.e. a sequence of decimal digits,
+-- evaluating to itself.
+--
+-- * A (signed) floating point value, as recoginzed by C\'s @atof()@, evaluating
+-- to itself.
+--
+-- * A pointer value of the form @\#p/num/@, where /num/ can be an octal,
+-- decimal or hexadecimal value, as recoginzed by C\`s @strtol()@, evaluating
+-- to itself. This kind of expression is currently unused.
+--
+-- * A string, i.e. a sequence of printable\/whitespace characters between
+-- double quotes, evaluating to itself.
+--
+-- * A symbol, i.e. a sequence of almost all characters which don\'t form a
+-- simple expression like the ones mentioned below, e.g. @foo@, @bar1@, @3baz@,
+-- ... The symbol evaluates to the value currently bound to it.
+--
+-- * A function application of the form @(/symbol/ /expression/...)@. The
+-- function bound to the symbol is applied to the evaluated arguments.
+-- 
+-- * A quotation of the form @(quote /expression/)@ or @\'/expression/@,
+-- evaluating to the unevaluated /expression/ itself.
+--
+-- * A definition of the form @(define /symbol/ /expression/)@, binding /symbol/
+-- to the value of /expression/. The whole expression evaluates to the value of
+-- /expression/, too.
+--
+-- * A conjunction of boolean expressions of the form @(and /expression/...)@.
+-- Each /expression/ is evaluated in turn, and if one of them evaluates to
+-- /false/, the value of the whole expression is /false/. Otherwise the value is
+-- /true/.
+--
+-- * An extension loading mechanism of the form @(load-extension
+-- /libraryName/)@, where /libraryName/ has to evaluate to a string. This tries
+-- to load the dynamic library with up to 3 special entry points:
+-- @alExtension_03282000@ (pointing to a mandatory NULL-terminated sequence of
+-- pairs of pointers to names and extension functions), @alExtInit_03282000@ (an
+-- optional initialization function), and @alExtFini_03282000@ (an optional
+-- cleanup function). If the extension could be loaded successfully, the whole
+-- expression evaluates to /true/, otherwise to /false/.
+--
+-- Some symbols have a special meaning for OpenAL:
+--
+-- [@devices@] Has the form @(/devspec/...)@, where /devspec/ is either a
+-- symbol\/string specifying a device or @(/device/ /device-param/...)@,
+-- specifying a device with additional parameters. These optional device
+-- parameters are stored in a variable @device-params@, but are currently
+-- unused. The first device which can successfully opened is used.
+--
+-- [@direction@] Type string or symbol: @\"read\"@ specifies that the device
+-- should be an input device, everything else means output device (default).
+--
+-- [@sampling-rate@] Type integer or float: Specifies the internal mixing
+-- frequency, default is 44.1kHz.
+--
+-- [@speaker-num@] Type integer or float: Specifies the number of speakers,
+-- which can be 1, 2 (default), or 4.
+--
+-- [@alsa-device@] Type string, @alsa@ backend only: Specifies both
+-- @alsa-out-device@ and @alsa-in-device@, default @\"plughw:0,0\"@.
+-- 
+-- [@alsa-out-device@] Type string, @alsa@ backend only: Specifies the ALSA
+-- output device, defaults to the value of @alsa-device@.
+--
+-- [@alsa-in-device@] Type string, @alsa@ backend only: Specifies the ALSA
+-- input device, defaults to the value of @alsa-device@.
+--
+-- [@native-in-device@] Type string, @native@ backend on IRIX only.
+--
+-- [@native-out-device@] Type string, @native@ backend on IRIX only.
+--
+-- [@native-rear-out-device@] Type string, @native@ backend on IRIX only.
+--
+-- [@native-use-select@] Type boolean, @native@ backend on Linux only: If @\#t@,
+-- wait up to 0.8sec for the device to become ready for writing. If @\#f@, just
+-- try to write and hope it won\'t hang forever. The latter might be necessary
+-- for some drivers which don\'t implement @select()@ , like some Aureal
+-- drivers.
+--
+-- [@lin-dsp-path@] Type string, @native@ backend on Linux only: Path to DSP
+-- device for writing, tried before @\/dev\/sound\/dsp@ and @\/dev\/sound@ if
+-- set.
+--
+-- [@lin-dsp-read-path@] Type string, @native@ backend on Linux only: Path to
+-- DSP device for reading, tried before @\/dev\/sound\/dsp@ and @\/dev\/sound@
+-- if set. Defaults to the value of @lin-dsp-path@.
+--
+-- [@native-backend-debug@] Type boolean, @native@ backend on Darwin only: If
+-- set to @\#f@, be a bit verbose on stderr about what\'s going on in the
+-- backend.
+--
+-- [@source-rolloff-factor@] Type integer or float: Value of the initial rolloff
+-- factor for sources, default is @1.0@.
+--
+-- [@listener-position@] List of 3 integers or floats: Value of the initial
+-- listener position, default is @(0 0 0)@.
+--
+-- [@listener-velocity@] List of 3 integers or floats: Value of the initial
+-- listener velocity, default is @(0 0 0)@.
+--
+-- [@listener-orientation@] List of 6 integers or floats: Value of the initial
+-- listener orientation (at\/up), default is @(0 0 -1 0 1 0)@.
+--
+-- The string given to 'openDevice' has to be of the form @\'((/symbol/
+-- /expression/) ...)@, which means basically a sequence of @define@
+-- expressions. Example:
+--
+-- @
+-- \"\'((sampling-rate 8000) (native-backend-debug \#f))\"
+-- @
+--
+-- /Note:/ The information above has been reverse-engineered from the OpenAL SI
+-- and could be inaccurate. Any corrections and\/or additions are highly
+-- welcome.
+
+openDevice :: Maybe String -> IO (Maybe Device)
+openDevice maybeDeviceSpec =
+   fmap unmarshalDevice $
+      maybe (alcOpenDevice nullPtr)   -- use preferred device
+            (flip withALCString alcOpenDevice)
+            maybeDeviceSpec
+
+foreign import ccall unsafe "alcOpenDevice"
+   alcOpenDevice :: Ptr ALCchar -> IO ALCdevice
+
+--------------------------------------------------------------------------------
+
+-- | Contains 'Just' the specifier string for the default device or 'Nothing' if
+-- there is no sound support at all.
+
+defaultDeviceSpecifier :: GettableStateVar (Maybe String)
+defaultDeviceSpecifier = makeGettableStateVar $
+   getStringRaw Nothing DefaultDeviceSpecifier >>= maybePeek peekALCString
+
+--------------------------------------------------------------------------------
+
+-- | Contains the specifier string for the given device.
+
+deviceSpecifier :: Device -> GettableStateVar String
+deviceSpecifier device = makeGettableStateVar $
+   getString (Just device) DeviceSpecifier
+
+--------------------------------------------------------------------------------
+
+-- | Contains a list of specifiers for all available devices.
+
+allDeviceSpecifiers :: GettableStateVar [String]
+allDeviceSpecifiers = makeGettableStateVar $ do
+   enumExtPresent <- get (alcIsExtensionPresent Nothing "ALC_ENUMERATION_EXT")
+   if enumExtPresent
+      then getStringRaw Nothing DeviceSpecifier >>= peekALCStrings
+      else get defaultDeviceSpecifier >>= (return . maybe [] (\s -> [s]))
diff --git a/src/Sound/OpenAL/ALC/Errors.hs b/src/Sound/OpenAL/ALC/Errors.hs
new file mode 100644
--- /dev/null
+++ b/src/Sound/OpenAL/ALC/Errors.hs
@@ -0,0 +1,93 @@
+--------------------------------------------------------------------------------
+-- |
+-- Module      :  Sound.OpenAL.ALC.Errors
+-- Copyright   :  (c) Sven Panne 2003-2013
+-- License     :  BSD3
+-- 
+-- Maintainer  :  Sven Panne <svenpanne@gmail.com>
+-- Stability   :  stable
+-- Portability :  portable
+--
+-- This module corresponds to section 6.3.6 (Query for Error Conditions) of the
+-- OpenAL Specification and Reference (version 1.1).
+--
+--------------------------------------------------------------------------------
+
+module Sound.OpenAL.ALC.Errors (
+   ALCError(..), ALCErrorCategory(..), alcErrors
+) where
+
+import Foreign.C.Types
+import Graphics.Rendering.OpenGL.GL.StateVar
+import Sound.OpenAL.ALC.BasicTypes ( ALCenum )
+import Sound.OpenAL.ALC.Device ( Device )
+import Sound.OpenAL.ALC.QueryUtils ( StringQuery(..), getString )
+import Sound.OpenAL.Constants (
+   alc_NO_ERROR, alc_INVALID_DEVICE, alc_INVALID_CONTEXT, alc_INVALID_ENUM,
+   alc_INVALID_VALUE, alc_OUT_OF_MEMORY, alc_INVALID_OPERATION )
+import Sound.OpenAL.Config ( ALCdevice(..), marshalDevice )
+
+--------------------------------------------------------------------------------
+
+-- | ALC errors consist of a general error category and a description of what
+-- went wrong.
+
+data ALCError = ALCError ALCErrorCategory String
+   deriving ( Eq, Ord, Show )
+
+--------------------------------------------------------------------------------
+
+-- | General ALC error categories.
+
+data ALCErrorCategory =
+     ALCInvalidEnum
+   | ALCInvalidValue
+   | ALCInvalidOperation
+   | ALCInvalidDevice
+   | ALCInvalidContext
+   | ALCOutOfMemory
+   deriving ( Eq, Ord, Show )
+
+unmarshalALCErrorCategory :: ALCenum -> ALCErrorCategory
+unmarshalALCErrorCategory x
+   | x == alc_INVALID_ENUM = ALCInvalidEnum
+   | x == alc_INVALID_VALUE = ALCInvalidValue
+   | x == alc_INVALID_OPERATION = ALCInvalidOperation
+   | x == alc_INVALID_DEVICE = ALCInvalidDevice
+   | x == alc_INVALID_CONTEXT = ALCInvalidContext
+   | x == alc_OUT_OF_MEMORY = ALCOutOfMemory
+   | otherwise = error ("unmarshalALCErrorCategory: illegal value " ++ show x)
+
+--------------------------------------------------------------------------------
+
+-- | OpenAL detects only a subset of those conditions that could be considered
+-- errors. This is because in many cases error checking would adversely impact
+-- the performance of an error-free program. The state variable 'alcErrors' is
+-- used to obtain error information. When an error is detected by ALC, a flag is
+-- set and the error code is recorded. Further errors, if they occur, do not
+-- affect this recorded code. When 'alcErrors' is read, the error for the given
+-- device is returned and the flag is cleared, so that a further error will
+-- again record its code. If reading 'alcErrors' returns @\[\]@ then there has
+-- been no detectable error since the last time 'alcErrors' (or since the ALC
+-- was initialized).
+--
+-- When an error flag is set, results of ALC operations are undefined only if
+-- 'ALCOutOfMemory' has occurred. In other cases, the command generating the
+-- error is ignored so that it has no effect on ALC state or output buffer
+-- contents. If the error generating command returns a value, it returns zero.
+-- If the generating command modifies values through a pointer argument, no
+-- change is made to these values. These error semantics apply only to ALC
+-- errors, not to system errors such as memory access errors.
+
+alcErrors :: Device -> GettableStateVar [ALCError]
+alcErrors device =
+   makeGettableStateVar $ do
+      c <- alcGetError (marshalDevice device)
+      if c == alc_NO_ERROR
+         then return []
+         else do
+            s <- getString (Just device) (ALCErrorCategory c)
+            return [ ALCError (unmarshalALCErrorCategory c) s ]
+
+foreign import ccall unsafe "alcGetError"
+   alcGetError :: ALCdevice -> IO ALCenum
diff --git a/src/Sound/OpenAL/ALC/Extensions.hs b/src/Sound/OpenAL/ALC/Extensions.hs
new file mode 100644
--- /dev/null
+++ b/src/Sound/OpenAL/ALC/Extensions.hs
@@ -0,0 +1,86 @@
+--------------------------------------------------------------------------------
+-- |
+-- Module      :  Sound.OpenAL.ALC.Extensions
+-- Copyright   :  (c) Sven Panne 2003-2013
+-- License     :  BSD3
+-- 
+-- Maintainer  :  Sven Panne <svenpanne@gmail.com>
+-- Stability   :  stable
+-- Portability :  portable
+--
+-- This module corresponds to the extension handling parts of section 6.3
+-- (ALC Queries) of the OpenAL Specification and Reference (version 1.1).
+--
+--------------------------------------------------------------------------------
+
+module Sound.OpenAL.ALC.Extensions (
+   alcExtensions, alcIsExtensionPresent, alcProcAddress, alcEnumValue,
+   alcVersion
+) where
+
+import Control.Monad ( liftM2 )
+import Graphics.Rendering.OpenGL.GL.StateVar
+import Foreign.C.Types
+import Foreign.Ptr ( Ptr, FunPtr )
+import Sound.OpenAL.ALC.BasicTypes ( ALCchar, ALCenum, ALCint )
+import Sound.OpenAL.ALC.Device ( Device )
+import Sound.OpenAL.ALC.QueryUtils (
+   StringQuery(..), getString, IntQuery(..), getInteger, alcIsExtensionPresent )
+import Sound.OpenAL.ALC.String ( withALCString )
+import Sound.OpenAL.Config ( ALCdevice(..), nullDevice, marshalDevice )
+
+--------------------------------------------------------------------------------
+
+-- | Contains a list of available context extensions.
+
+alcExtensions :: Device -> GettableStateVar [String]
+alcExtensions device = makeGettableStateVar $
+   fmap words $ getString (Just device) Extensions
+
+--------------------------------------------------------------------------------
+
+-- | The application is expected to verify the applicability of an extension or
+-- core function entry point before requesting it by name, by use of
+-- 'alcIsExtensionPresent'. Extension entry points can be retrieved using
+-- 'alcProcAddress'. Entry points can be device specific, but are not context
+-- specific. Using 'Nothing' as the device does not guarantee that the entry
+-- point is returned, even if available for one of the available devices.
+
+alcProcAddress :: Maybe Device -> String -> GettableStateVar (FunPtr a)
+alcProcAddress maybeDevice funcName =
+   makeGettableStateVar .
+      withALCString funcName .
+         alcGetProcAddress . marshalDevice . maybe nullDevice id $ maybeDevice
+
+foreign import ccall unsafe "alcGetProcAddress"
+   alcGetProcAddress :: ALCdevice -> Ptr ALCchar -> IO (FunPtr a)
+
+--------------------------------------------------------------------------------
+
+-- | Enumeration\/token values are device independent, but tokens defined for
+-- extensions might not be present for a given device. Using 'Nothing' as the
+-- device is legal, but only the tokens defined by the AL core are
+-- guaranteed. Availability of extension tokens depends on the ALC extension.
+
+alcEnumValue :: Maybe Device -> String -> GettableStateVar ALCenum
+alcEnumValue maybeDevice enumName =
+   makeGettableStateVar .
+      withALCString enumName .
+         alcGetEnumValue . marshalDevice . maybe nullDevice id $ maybeDevice
+
+foreign import ccall unsafe "alcGetEnumValue"
+   alcGetEnumValue :: ALCdevice -> Ptr ALCchar -> IO ALCenum
+
+--------------------------------------------------------------------------------
+
+-- | Contains the \"/major/./minor/\" specification revision for this implementation.
+
+alcVersion :: GettableStateVar String
+alcVersion =
+   makeGettableStateVar $
+      liftM2 makeVersionString
+             (getInteger Nothing MajorVersion)
+             (getInteger Nothing MinorVersion)
+
+makeVersionString :: ALCint -> ALCint -> String
+makeVersionString major minor = show major ++ "." ++ show minor
diff --git a/src/Sound/OpenAL/ALC/QueryUtils.hs b/src/Sound/OpenAL/ALC/QueryUtils.hs
new file mode 100644
--- /dev/null
+++ b/src/Sound/OpenAL/ALC/QueryUtils.hs
@@ -0,0 +1,122 @@
+{-# OPTIONS_HADDOCK hide #-}
+--------------------------------------------------------------------------------
+-- |
+-- Module      :  Sound.OpenAL.ALC.QueryUtils
+-- Copyright   :  (c) Sven Panne 2003-2013
+-- License     :  BSD3
+-- 
+-- Maintainer  :  Sven Panne <svenpanne@gmail.com>
+-- Stability   :  stable
+-- Portability :  portable
+--
+--------------------------------------------------------------------------------
+
+module Sound.OpenAL.ALC.QueryUtils (
+   StringQuery(..), getString, getStringRaw,
+   IntQuery(..), marshalIntQuery, getInteger, getIntegerv,
+   alcIsExtensionPresent
+) where
+
+import Control.Monad ( when )
+import Graphics.Rendering.OpenGL.GL.StateVar
+import Foreign.C.Types
+import Foreign.Marshal.Array ( withArray, peekArray )
+import Foreign.Ptr ( Ptr )
+import Sound.OpenAL.ALC.ALCboolean ( unmarshalALCboolean )
+import Sound.OpenAL.ALC.BasicTypes (
+   ALCboolean, ALCchar, ALCint, ALCenum, ALCsizei )
+import Sound.OpenAL.ALC.String ( withALCString, peekALCString )
+import Sound.OpenAL.Config ( Device, ALCdevice(..), nullDevice, marshalDevice )
+import Sound.OpenAL.Constants (
+   alc_DEFAULT_DEVICE_SPECIFIER, alc_DEVICE_SPECIFIER, alc_EXTENSIONS,
+   alc_CAPTURE_DEFAULT_DEVICE_SPECIFIER, alc_CAPTURE_DEVICE_SPECIFIER,
+   alc_ATTRIBUTES_SIZE, alc_ALL_ATTRIBUTES, alc_MAJOR_VERSION,
+   alc_MINOR_VERSION, alc_CAPTURE_SAMPLES )
+
+--------------------------------------------------------------------------------
+
+data StringQuery =
+     DefaultDeviceSpecifier
+   | DeviceSpecifier
+   | Extensions
+   | CaptureDefaultDeviceSpecifier
+   | CaptureDeviceSpecifier
+   | ALCErrorCategory ALCenum
+
+marshalStringQuery :: StringQuery -> ALCenum
+marshalStringQuery x = case x of
+   DefaultDeviceSpecifier -> alc_DEFAULT_DEVICE_SPECIFIER
+   DeviceSpecifier -> alc_DEVICE_SPECIFIER
+   Extensions -> alc_EXTENSIONS
+   CaptureDefaultDeviceSpecifier -> alc_CAPTURE_DEFAULT_DEVICE_SPECIFIER
+   CaptureDeviceSpecifier -> alc_CAPTURE_DEVICE_SPECIFIER
+   ALCErrorCategory e -> e
+
+--------------------------------------------------------------------------------
+
+getString :: Maybe Device -> StringQuery -> IO String
+getString device query = getStringRaw device query >>= peekALCString
+
+getStringRaw :: Maybe Device -> StringQuery -> IO (Ptr ALCchar)
+getStringRaw maybeDevice =
+   alcGetString (marshalMaybeDevice maybeDevice) . marshalStringQuery
+
+marshalMaybeDevice :: Maybe Device -> ALCdevice
+marshalMaybeDevice = marshalDevice . maybe nullDevice id
+
+foreign import ccall unsafe "alcGetString"
+   alcGetString :: ALCdevice -> ALCenum -> IO (Ptr ALCchar)
+
+--------------------------------------------------------------------------------
+
+data IntQuery =
+     AttributesSize
+   | AllAttributes
+   | MajorVersion
+   | MinorVersion
+   | CaptureSamples
+
+marshalIntQuery :: IntQuery -> ALCenum
+marshalIntQuery x = case x of
+   AttributesSize -> alc_ATTRIBUTES_SIZE
+   AllAttributes -> alc_ALL_ATTRIBUTES
+   MajorVersion -> alc_MAJOR_VERSION
+   MinorVersion -> alc_MINOR_VERSION
+   CaptureSamples -> alc_CAPTURE_SAMPLES
+
+--------------------------------------------------------------------------------
+
+getInteger :: Maybe Device -> IntQuery -> IO ALCint
+getInteger maybeDevice query = fmap head $ getIntegerv maybeDevice query 1
+
+-- We are extremely careful below to avoid segfaults in case that there is no
+-- current context, an invalid device, etc.
+getIntegerv :: Maybe Device -> IntQuery -> ALCsizei -> IO [ALCint]
+getIntegerv maybeDevice query numALCints =
+   let n = fromIntegral numALCints
+   in withArray (replicate n 0) $ \buf -> do
+         when (numALCints > 0) $
+            alcGetIntegerv (marshalMaybeDevice maybeDevice)
+                           (marshalIntQuery query) numALCints buf
+         peekArray n buf
+
+foreign import ccall unsafe "alcGetIntegerv"
+   alcGetIntegerv :: ALCdevice -> ALCenum -> ALCsizei -> Ptr ALCint -> IO ()
+
+--------------------------------------------------------------------------------
+
+-- | To verify that a given extension is available for the current context and
+-- the device it is associated with, use 'alcIsExtensionPresent'. For invalid
+-- and unsupported string tokens it contains 'False'. Using 'Nothing' as the
+-- device is acceptable. The extension name is not case sensitive: The
+-- implementation will convert the name to all upper-case internally (and will
+-- express extension names in upper-case).
+
+alcIsExtensionPresent :: Maybe Device -> String -> GettableStateVar Bool
+alcIsExtensionPresent maybeDevice extensionName = makeGettableStateVar $
+   fmap unmarshalALCboolean $
+      withALCString extensionName $
+         alcIsExtensionPresent_ (marshalMaybeDevice maybeDevice)
+
+foreign import ccall unsafe "alcIsExtensionPresent"
+   alcIsExtensionPresent_ :: ALCdevice -> Ptr ALCchar -> IO ALCboolean
diff --git a/src/Sound/OpenAL/ALC/String.hs b/src/Sound/OpenAL/ALC/String.hs
new file mode 100644
--- /dev/null
+++ b/src/Sound/OpenAL/ALC/String.hs
@@ -0,0 +1,42 @@
+{-# OPTIONS_HADDOCK hide #-}
+--------------------------------------------------------------------------------
+-- |
+-- Module      :  Sound.OpenAL.ALC.String
+-- Copyright   :  (c) Sven Panne 2003-2013
+-- License     :  BSD3
+-- 
+-- Maintainer  :  Sven Panne <svenpanne@gmail.com>
+-- Stability   :  stable
+-- Portability :  portable
+--
+--------------------------------------------------------------------------------
+
+module Sound.OpenAL.ALC.String (
+   withALCString, peekALCString, peekALCStrings
+) where
+
+import Foreign.C.String ( withCString, peekCString )
+import Foreign.Marshal.Array ( lengthArray0 )
+import Foreign.Ptr ( Ptr, castPtr, plusPtr )
+import Sound.OpenAL.ALC.BasicTypes ( ALCchar )
+
+--------------------------------------------------------------------------------
+
+-- AL uses "Ptr ALCchar" instead of "CString" for strings, so some wrappers
+-- are quite handy.
+
+withALCString :: String -> (Ptr ALCchar -> IO a) -> IO a
+withALCString str action = withCString str (action . castPtr)
+
+peekALCString :: Ptr ALCchar -> IO String
+peekALCString = peekCString . castPtr
+
+peekALCStrings :: Ptr ALCchar -> IO [String]
+peekALCStrings ptr = loop ptr []
+   where loop p strs = do
+            str <- peekALCString p
+            if str == ""
+               then return (reverse strs)
+               else do
+                  len <- lengthArray0 0 p
+                  loop (p `plusPtr` (len + 1)) (str : strs)
diff --git a/src/Sound/OpenAL/Config.hs b/src/Sound/OpenAL/Config.hs
new file mode 100644
--- /dev/null
+++ b/src/Sound/OpenAL/Config.hs
@@ -0,0 +1,191 @@
+{-# OPTIONS_HADDOCK hide #-}
+--------------------------------------------------------------------------------
+-- |
+-- Module      :  Sound.OpenAL.Config
+-- Copyright   :  (c) Sven Panne 2003-2013
+-- License     :  BSD3
+-- 
+-- Maintainer  :  Sven Panne <svenpanne@gmail.com>
+-- Stability   :  stable
+-- Portability :  portable
+--
+-- This purely internal module defines the platform-specific stuff which has
+-- been figured out by configure.
+--
+--------------------------------------------------------------------------------
+
+module Sound.OpenAL.Config (
+   -- AL types
+   ALboolean, ALchar, ALbyte, ALubyte, ALshort, ALushort, ALint, ALuint,
+   ALsizei, ALenum, ALfloat, ALdouble,
+
+   -- ALC types
+   ALCboolean, ALCchar, ALCbyte, ALCubyte, ALCshort, ALCushort, ALCint, ALCuint,
+   ALCsizei, ALCenum, ALCfloat, ALCdouble,
+
+   -- Device stuff
+   ALCdevice(ALCdevice), Device, nullDevice, marshalDevice, unmarshalDevice, closeDevice,
+
+   -- Context stuff
+   ALCcontext(..), Context, nullContext, marshalContext, unmarshalContext,
+   alcProcessContext, alcMakeContextCurrent, alcDestroyContext
+) where
+
+import Foreign.C.Types
+import Foreign.Ptr ( Ptr, nullPtr )
+
+--------------------------------------------------------------------------------
+-- AL types
+
+-- | 8-bit boolean
+type ALboolean = CChar
+
+-- | Character
+type ALchar = CChar
+
+-- | Signed 8-bit 2\'s complement integer
+type ALbyte = CSChar
+
+-- | Unsigned 8-bit integer
+type ALubyte = CUChar
+
+-- | Signed 16-bit 2\'s complement integer
+type ALshort = CShort
+
+-- | Unsigned 16-bit integer
+type ALushort = CUShort
+
+-- | Signed 32-bit 2\'s complement integer
+type ALint = CInt
+
+-- | Unsigned 32-bit integer
+type ALuint = CUInt
+
+-- | Non-negatitve 32-bit binary integer size
+type ALsizei = CInt
+
+-- | Enumerated 32-bit value
+type ALenum = CInt
+
+-- | 32-bit IEEE754 floating-point
+type ALfloat = CFloat
+
+-- | 64-bit IEEE754 floating-point
+type ALdouble = CDouble
+
+--------------------------------------------------------------------------------
+-- ALC types
+
+-- | 8-bit boolean
+type ALCboolean = CChar
+
+-- | Character
+type ALCchar = CChar
+
+-- | Signed 8-bit 2\'s complement integer
+type ALCbyte = CSChar
+
+-- | Unsigned 8-bit integer
+type ALCubyte = CUChar
+
+-- | Signed 16-bit 2\'s complement integer
+type ALCshort = CShort
+
+-- | Unsigned 16-bit integer
+type ALCushort = CUShort
+
+-- | Signed 32-bit 2\'s complement integer
+type ALCint = CInt
+
+-- | Unsigned 32-bit integer
+type ALCuint = CUInt
+
+-- | Non-negatitve 32-bit binary integer size
+type ALCsizei = CInt
+
+-- | Enumerated 32-bit value
+type ALCenum = CInt
+
+-- | 32-bit IEEE754 floating-point
+type ALCfloat = CFloat
+
+-- | 64-bit IEEE754 floating-point
+type ALCdouble = CDouble
+
+--------------------------------------------------------------------------------
+-- In OpenAL 1.1, alcCloseDevice() returns an ALCboolean, before it was void.
+-- To break a dependency cycle, we have to define the Device type here, too.
+
+-- | The abstract device type.
+
+newtype Device = Device ALCdevice
+   deriving ( Eq, Ord, Show )
+
+newtype ALCdevice = ALCdevice (Ptr ALCdevice)
+   deriving ( Eq, Ord, Show )
+
+nullDevice :: Device
+nullDevice = Device (ALCdevice nullPtr)
+
+marshalDevice :: Device -> ALCdevice
+marshalDevice (Device device) = device
+
+unmarshalDevice :: ALCdevice -> Maybe Device
+unmarshalDevice device =
+   if device == marshalDevice nullDevice then Nothing else Just (Device device)
+
+-- | 'closeDevice' allows the application (i.e. the client program) to
+-- disconnect from a device (i.e. the server). It returns 'True' for success and
+-- 'False' for failure. Once closed, the 'Device' is invalid.
+--
+-- /Note:/ Older OpenAL implementations will always report a success!
+
+closeDevice :: Device -> IO Bool
+-- inlined unmarshalALCboolean here to break dependency cycle
+closeDevice = fmap (/= 0) . alcCloseDevice . marshalDevice
+
+foreign import ccall unsafe "alcCloseDevice"
+   alcCloseDevice :: ALCdevice -> IO ALCboolean
+
+--------------------------------------------------------------------------------
+-- In OpenAL 1.1, alcProcessContext() returns void for all platforms, before it
+-- returned ALCcontext* on Linux. To break a dependency cycle, we have to define
+-- the Context type here, too.
+
+-- | The abstract context type.
+
+data Context = Context ALCcontext
+   deriving ( Eq, Ord, Show )
+
+newtype ALCcontext = ALCcontext (Ptr ALCcontext)
+   deriving ( Eq, Ord, Show )
+
+nullContext :: Context
+nullContext = Context (ALCcontext nullPtr)
+
+marshalContext :: Context -> ALCcontext
+marshalContext (Context context) = context
+
+unmarshalContext :: ALCcontext -> Maybe Context
+unmarshalContext context =
+   if context == marshalContext nullContext then Nothing else Just (Context context)
+
+--------------------------------------------------------------------------------
+-- In ancient times, alcProcessContext returned ALCcontext.
+
+foreign import ccall unsafe "alcProcessContext"
+   alcProcessContext :: ALCcontext -> IO ()
+
+--------------------------------------------------------------------------------
+-- In OpenAL 1.1, alcMakeContextCurrent() returns void, before it was ALCenum on
+-- Linux and ALCboolean on other platforms.
+
+foreign import ccall unsafe "alcMakeContextCurrent"
+   alcMakeContextCurrent :: ALCcontext -> IO ALCboolean
+
+--------------------------------------------------------------------------------
+-- In OpenAL 1.1, alcDestroyContext() returns void, before it returned ALCenum
+-- on Linux.
+
+foreign import ccall unsafe "alcDestroyContext"
+   alcDestroyContext :: ALCcontext -> IO ()
diff --git a/src/Sound/OpenAL/Constants.hs b/src/Sound/OpenAL/Constants.hs
new file mode 100644
--- /dev/null
+++ b/src/Sound/OpenAL/Constants.hs
@@ -0,0 +1,162 @@
+{-# OPTIONS_HADDOCK hide #-}
+--------------------------------------------------------------------------------
+-- |
+-- Module      :  Sound.OpenAL.Constants
+-- Copyright   :  (c) Sven Panne 2003-2013
+-- License     :  BSD3
+-- 
+-- Maintainer  :  Sven Panne <svenpanne@gmail.com>
+-- Stability   :  stable
+-- Portability :  portable
+--
+-- This purely internal module defines all AL\/ALC constants, which have been
+-- figured out by configure. In contrast to OpenGL and GLUT, these constants
+-- varied on different platforms in the past and have evolved quite a bit.
+--
+--------------------------------------------------------------------------------
+
+module Sound.OpenAL.Constants where
+
+import Sound.OpenAL.Config (
+   ALboolean, ALint, ALenum, ALCboolean, ALCint, ALCenum )
+
+--------------------------------------------------------------------------------
+
+al_FALSE, al_TRUE :: ALboolean
+al_FALSE                            = 0x0000
+al_TRUE                             = 0x0001
+
+al_NO_ERROR, al_INVALID_NAME, al_INVALID_ENUM, al_INVALID_VALUE,
+   al_INVALID_OPERATION, al_OUT_OF_MEMORY :: ALenum
+al_NO_ERROR                         = 0x0000
+al_INVALID_NAME                     = 0xA001
+al_INVALID_ENUM                     = 0xA002
+al_INVALID_VALUE                    = 0xA003
+al_INVALID_OPERATION                = 0xA004
+al_OUT_OF_MEMORY                    = 0xA005
+
+--------------------------------------------------------------------------------
+
+al_DISTANCE_MODEL, al_DOPPLER_FACTOR, al_SPEED_OF_SOUND :: ALenum
+al_DISTANCE_MODEL                   = 0xD000
+al_DOPPLER_FACTOR                   = 0xC000
+al_SPEED_OF_SOUND                   = 0xC003
+
+al_VERSION, al_RENDERER, al_VENDOR, al_EXTENSIONS :: ALenum
+al_VERSION                          = 0xB002
+al_RENDERER                         = 0xB003
+al_VENDOR                           = 0xB001
+al_EXTENSIONS                       = 0xB004
+
+al_NONE, al_INVERSE_DISTANCE, al_INVERSE_DISTANCE_CLAMPED, al_LINEAR_DISTANCE,
+   al_LINEAR_DISTANCE_CLAMPED, al_EXPONENT_DISTANCE,
+   al_EXPONENT_DISTANCE_CLAMPED :: ALenum
+al_NONE                             = 0x0000
+al_INVERSE_DISTANCE                 = 0xD001
+al_INVERSE_DISTANCE_CLAMPED         = 0xD002
+al_LINEAR_DISTANCE                  = 0xD003
+al_LINEAR_DISTANCE_CLAMPED          = 0xD004
+al_EXPONENT_DISTANCE                = 0xD005
+al_EXPONENT_DISTANCE_CLAMPED        = 0xD006
+
+--------------------------------------------------------------------------------
+
+al_POSITION, al_VELOCITY, al_GAIN :: ALenum
+al_POSITION                         = 0x1004
+al_VELOCITY                         = 0x1006
+al_GAIN                             = 0x100A
+
+al_ORIENTATION :: ALenum
+al_ORIENTATION                      = 0x100F
+
+al_SOURCE_RELATIVE, al_SOURCE_TYPE, al_LOOPING, al_BUFFER, al_BUFFERS_QUEUED,
+   al_BUFFERS_PROCESSED, al_MIN_GAIN, al_MAX_GAIN, al_REFERENCE_DISTANCE,
+   al_ROLLOFF_FACTOR, al_MAX_DISTANCE, al_PITCH, al_DIRECTION,
+   al_CONE_INNER_ANGLE, al_CONE_OUTER_ANGLE, al_CONE_OUTER_GAIN, al_SEC_OFFSET,
+   al_SAMPLE_OFFSET, al_BYTE_OFFSET, al_SOURCE_STATE :: ALenum
+al_SOURCE_RELATIVE                  = 0x0202
+al_SOURCE_TYPE                      = 0x1027
+al_LOOPING                          = 0x1007
+al_BUFFER                           = 0x1009
+al_BUFFERS_QUEUED                   = 0x1015
+al_BUFFERS_PROCESSED                = 0x1016
+al_MIN_GAIN                         = 0x100D
+al_MAX_GAIN                         = 0x100E
+al_REFERENCE_DISTANCE               = 0x1020
+al_ROLLOFF_FACTOR                   = 0x1021
+al_MAX_DISTANCE                     = 0x1023
+al_PITCH                            = 0x1003
+al_DIRECTION                        = 0x1005
+al_CONE_INNER_ANGLE                 = 0x1001
+al_CONE_OUTER_ANGLE                 = 0x1002
+al_CONE_OUTER_GAIN                  = 0x1022
+al_SEC_OFFSET                       = 0x1024
+al_SAMPLE_OFFSET                    = 0x1025
+al_BYTE_OFFSET                      = 0x1026
+al_SOURCE_STATE                     = 0x1010
+
+al_UNDETERMINED, al_STATIC, al_STREAMING :: ALint
+al_UNDETERMINED                     = 0x1030
+al_STATIC                           = 0x1028
+al_STREAMING                        = 0x1029
+
+al_INITIAL, al_PLAYING, al_PAUSED, al_STOPPED :: ALint
+al_INITIAL                          = 0x1011
+al_PLAYING                          = 0x1012
+al_PAUSED                           = 0x1013
+al_STOPPED                          = 0x1014
+
+--------------------------------------------------------------------------------
+
+al_FREQUENCY, al_SIZE, al_BITS, al_CHANNELS :: ALenum
+al_FREQUENCY                        = 0x2001
+al_SIZE                             = 0x2004
+al_BITS                             = 0x2002
+al_CHANNELS                         = 0x2003
+
+al_FORMAT_MONO8, al_FORMAT_MONO16, al_FORMAT_STEREO8,
+   al_FORMAT_STEREO16 :: ALenum
+al_FORMAT_MONO8                     = 0x1100
+al_FORMAT_MONO16                    = 0x1101
+al_FORMAT_STEREO8                   = 0x1102
+al_FORMAT_STEREO16                  = 0x1103
+
+--------------------------------------------------------------------------------
+
+alc_FALSE, alc_TRUE :: ALCboolean
+alc_FALSE                           = 0x0000
+alc_TRUE                            = 0x0001
+
+alc_FREQUENCY, alc_REFRESH, alc_SYNC, alc_MONO_SOURCES,
+   alc_STEREO_SOURCES :: ALCint
+alc_FREQUENCY                       = 0x1007
+alc_REFRESH                         = 0x1008
+alc_SYNC                            = 0x1009
+alc_MONO_SOURCES                    = 0x1010
+alc_STEREO_SOURCES                  = 0x1011
+
+alc_NO_ERROR, alc_INVALID_DEVICE, alc_INVALID_CONTEXT, alc_INVALID_ENUM,
+   alc_INVALID_VALUE, alc_INVALID_OPERATION, alc_OUT_OF_MEMORY :: ALCenum
+alc_NO_ERROR                        = 0x0000
+alc_INVALID_DEVICE                  = 0xA001
+alc_INVALID_CONTEXT                 = 0xA002
+alc_INVALID_ENUM                    = 0xA003
+alc_INVALID_VALUE                   = 0xA004
+alc_INVALID_OPERATION               = 0xA006
+alc_OUT_OF_MEMORY                   = 0xA005
+
+alc_DEFAULT_DEVICE_SPECIFIER, alc_DEVICE_SPECIFIER, alc_EXTENSIONS,
+   alc_CAPTURE_DEFAULT_DEVICE_SPECIFIER, alc_CAPTURE_DEVICE_SPECIFIER :: ALCenum
+alc_DEFAULT_DEVICE_SPECIFIER        = 0x1004
+alc_DEVICE_SPECIFIER                = 0x1005
+alc_EXTENSIONS                      = 0x1006
+alc_CAPTURE_DEFAULT_DEVICE_SPECIFIER= 0x0311
+alc_CAPTURE_DEVICE_SPECIFIER        = 0x0310
+
+alc_ATTRIBUTES_SIZE, alc_ALL_ATTRIBUTES, alc_MAJOR_VERSION, alc_MINOR_VERSION,
+   alc_CAPTURE_SAMPLES :: ALCenum
+alc_ATTRIBUTES_SIZE                 = 0x1002
+alc_ALL_ATTRIBUTES                  = 0x1003
+alc_MAJOR_VERSION                   = 0x1000
+alc_MINOR_VERSION                   = 0x1001
+alc_CAPTURE_SAMPLES                 = 0x0312
