diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,25 @@
+Copyright (c) 2009 Daiki Handa
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+3. The name of the author may not be used to endorse or promote products
+   derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,3 @@
+import Distribution.Simple
+main=defaultMain
+
diff --git a/Sound/Pulse/Simple.hsc b/Sound/Pulse/Simple.hsc
new file mode 100644
--- /dev/null
+++ b/Sound/Pulse/Simple.hsc
@@ -0,0 +1,263 @@
+{-# LANGUAGE ForeignFunctionInterface #-}
+-- |
+-- Maintainer:  xanxys@gmail.com
+-- Stability:   experimental
+-- Portability: non-portable
+--
+-- Binding to PulseAudio Simple API
+--
+-- example(output 440Hz sine wave for 10 seconds):
+-- 
+-- @
+--  main=do
+--      s<-simpleNew Nothing \"example\" Play Nothing \"this is example application\"
+--          (SampleSpec (F32 LittleEndian) 44100 1) Nothing Nothing
+--      simpleWrite s [sin $ 2*pi*440*(t/44100)|t<-[1..44100*10]]
+--      simpleDrain s
+--      simpleFree s
+-- @
+module Sound.Pulse.Simple
+    (simpleNew
+    ,simpleFree
+    ,simpleGetLatency
+    ,simpleRead
+    ,simpleReadRaw
+    ,simpleWrite
+    ,simpleWriteRaw
+    ,simpleDrain
+    ,simpleFlush
+    ,Simple
+    ,SampleSpec(..)
+    ,SampleFormat(..)
+    ,Compression(..)
+    ,Endian(..)
+    ,Direction(..)
+    ,ChannelPosition(..)
+    ,ChannelPan(..)
+    ,BufferAttr(..))
+    where
+import Control.Monad
+import qualified Data.ByteString as BS
+import qualified Data.ByteString.Internal as BS
+import Foreign.C
+import Foreign.Marshal.Alloc
+import Foreign.Marshal.Array
+import Foreign.Ptr
+import Foreign.ForeignPtr
+import Foreign.Storable
+
+
+#include <pulse/simple.h>
+#let alignment t = "%lu", (unsigned long)offsetof(struct {char x__; t (y__); }, y__)
+
+
+
+
+foreign import ccall "pa_simple_new" pasNew
+    :: CString -> CString -> CInt -> CString -> CString -> Ptr SampleSpec -> Ptr ChannelMap
+    -> Ptr BufferAttr -> Ptr CInt -> IO (Ptr PASimple)
+foreign import ccall "pa_simple_free" pasFree :: Ptr PASimple -> IO ()
+foreign import ccall "pa_simple_write" pasWrite :: Ptr PASimple -> Ptr CUChar -> CInt -> Ptr CInt -> IO CInt
+foreign import ccall "pa_simple_read" pasRead :: Ptr PASimple -> Ptr CUChar -> CInt -> Ptr CInt -> IO CInt
+foreign import ccall "pa_simple_drain" pasDrain :: Ptr PASimple -> Ptr CInt -> IO CInt
+foreign import ccall "pa_simple_get_latency" pasGetLatency :: Ptr PASimple -> Ptr CInt -> IO CUInt -- 64 bit dep.
+foreign import ccall "pa_simple_flush" pasFlush :: Ptr PASimple -> IO CInt
+
+
+newtype Simple=Simple (Ptr PASimple)
+data Direction=Play|Record
+
+
+data SampleSpec=SampleSpec SampleFormat Int Int -- ^ format, sampling rate, #channels
+
+data SampleFormat
+    =U8 Compression
+    |S16 Endian
+    |S24 Endian
+    |S2432 Endian -- ^ 24 bit sample in 32 bit
+    |S32 Endian
+    |F32 Endian
+data Compression=Raw|ALaw|MuLaw
+data Endian=BigEndian|LittleEndian
+
+newtype ChannelMap=ChannelMap [ChannelPosition]
+data ChannelPosition
+    =ChannelMono
+    |ChannelNormal   ChannelPan
+    |ChannelFront    ChannelPan
+    |ChannelRear     ChannelPan
+    |ChannelTopRear  ChannelPan
+    |ChannelTopFront ChannelPan
+    |ChannelLFE -- ^ low frequency effects
+    |ChannelSubwoofer
+    |ChannelFrontCenterLeft -- ^ equivalent to PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER
+    |ChannelFrontCenterRight
+    |ChannelSideLeft
+    |ChannelSideRight
+    |ChannelTopCenter
+    |ChannelAux Int -- 0-31
+
+
+data ChannelPan=PanLeft|PanRight|PanCenter
+    
+
+
+data BufferAttr=BufferAttr (Maybe Int) (Maybe Int) (Maybe Int) (Maybe Int) (Maybe Int)
+-- ^ max length, target length, prebuffer, minimum request, fragment size
+
+
+-- hidden struct
+data PASimple=PASimple
+
+
+
+
+
+
+
+instance Enum Direction where
+    toEnum=undefined
+    fromEnum Play=1
+    fromEnum Record=2
+
+instance Storable SampleSpec where
+    alignment _= #{alignment pa_sample_spec}
+    sizeOf _= #{size pa_sample_spec}
+    poke ptr (SampleSpec fmt rate nch)=do
+        #{poke pa_sample_spec,format}   ptr $ fromEnum fmt
+        #{poke pa_sample_spec,rate}     ptr rate
+        #{poke pa_sample_spec,channels} ptr nch
+
+instance Enum SampleFormat where
+    toEnum=undefined
+    fromEnum (U8 Raw)=0
+    fromEnum (U8 ALaw)=1
+    fromEnum (U8 MuLaw)=2
+    fromEnum x=case x of
+        S16 e -> 3+f e
+        F32 e -> 5+f e
+        S32 e -> 7+f e
+        S24 e -> 9+f e
+        S2432 e -> 11+f e
+        where f LittleEndian=0; f BigEndian=1
+
+instance Storable ChannelMap where
+    alignment _= #{alignment pa_channel_map}
+    sizeOf _= #{alignment pa_channel_map}
+    poke ptr (ChannelMap ps)=withArray (map fromEnum ps) $ \_ps -> do
+        #{poke pa_channel_map,channels} ptr $ length ps
+        #{poke pa_channel_map,map} ptr _ps
+
+instance Enum ChannelPosition where
+    toEnum=undefined
+    fromEnum x=case x of
+        ChannelMono -> 0
+        ChannelNormal p -> 1+f p
+        ChannelFront p -> 1+f p
+        ChannelRear p -> 4+f p
+        ChannelLFE -> 7
+        ChannelSubwoofer -> 7
+        ChannelFrontCenterLeft -> 8
+        ChannelFrontCenterRight -> 9
+        ChannelSideLeft -> 10
+        ChannelSideRight -> 11
+        ChannelAux n -> 12+n
+        ChannelTopCenter -> 44
+        ChannelTopFront p -> 45+f p
+        ChannelTopRear p -> 48+f p
+        where f PanLeft=0; f PanRight=1; f PanCenter=2
+
+instance Storable BufferAttr where
+    alignment _= #{alignment pa_buffer_attr}
+    sizeOf _= #{alignment pa_buffer_attr}
+    poke ptr (BufferAttr ml tl pb mr fs)=do
+        #{poke pa_buffer_attr,maxlength} ptr $ f ml
+        #{poke pa_buffer_attr,tlength}   ptr $ f tl
+        #{poke pa_buffer_attr,prebuf}    ptr $ f pb
+        #{poke pa_buffer_attr,minreq}    ptr $ f mr
+        #{poke pa_buffer_attr,fragsize}  ptr $ f fs
+        where f=maybe 0xffffffff id
+
+
+ 
+
+
+-- | Establish connection to pulseaudio server. You usually don't need to specify optional fields.
+simpleNew
+    :: Maybe String -- ^ server name
+    -> String -- ^ client name
+    -> Direction -- ^ Play or Record
+    -> Maybe String -- ^ name of sink or source
+    -> String -- ^ description of client
+    -> SampleSpec
+    -> Maybe [ChannelPosition] -- ^ label channels
+    -> Maybe BufferAttr -- ^ buffer size, etc
+    -> IO Simple
+simpleNew server client dir dev desc spec chmap attr=liftM Simple $
+    withMaybeCString server $ \_server->
+    withCString client $ \_client ->
+    withMaybeCString dev $ \_dev ->
+    withCString desc $ \_desc ->
+    withStorable spec $ \_spec -> 
+    withMaybeStorable (liftM ChannelMap chmap) $ \_chmap ->
+    withMaybeStorable attr $ \_attr ->
+        pasNew _server _client (fromIntegral $ fromEnum dir) _dev _desc _spec _chmap _attr nullPtr
+
+
+-- | Read raw data from buffer.
+simpleReadRaw :: Simple -> Int -> IO BS.ByteString
+simpleReadRaw (Simple x) size=
+    BS.create size $ \ptr->pasRead x (castPtr ptr) (fromIntegral size) nullPtr >> return ()
+
+-- | Write raw data to buffer.
+simpleWriteRaw :: Simple -> BS.ByteString -> IO ()
+simpleWriteRaw (Simple x) (BS.PS ptr ofs size)=do
+    withForeignPtr ptr $ \p->pasWrite x (castPtr p) (fromIntegral size) nullPtr
+    return ()
+
+-- | Read from buffer.
+simpleRead :: Storable a => Simple -> Int -> IO [a]
+simpleRead s n=simpleReadHack undefined s n
+
+simpleReadHack :: Storable a => a -> Simple -> Int -> IO [a]
+simpleReadHack dummy (Simple x) n=do
+    let size=fromIntegral $ n*sizeOf dummy
+    rs<-allocaArray n $ \ptr->pasRead x (castPtr ptr) size nullPtr >> peekArray n ptr
+    return rs
+    
+-- | Write to buffer.
+simpleWrite :: Storable a => Simple -> [a] -> IO ()
+simpleWrite (Simple x) xs=do
+    let n=length xs
+        size=fromIntegral $ n*sizeOf (head xs)
+    allocaArray n $ \ptr->pokeArray ptr xs >> pasWrite x (castPtr ptr) size nullPtr
+    return ()
+
+-- | Flush playback buffer
+simpleFlush :: Simple -> IO ()
+simpleFlush (Simple x)=pasFlush x >> return ()
+
+-- | block until buffer is completely consumed
+simpleDrain :: Simple -> IO ()
+simpleDrain (Simple x)=pasDrain x nullPtr >> return ()
+
+-- | Close the connection.
+simpleFree :: Simple -> IO ()
+simpleFree (Simple x)=pasFree x
+
+-- | Get current latency in microseconds.
+simpleGetLatency :: Simple -> IO Integer
+simpleGetLatency (Simple x)=liftM fromIntegral $ pasGetLatency x nullPtr
+
+
+withMaybeStorable :: Storable a => Maybe a -> (Ptr a -> IO b) -> IO b
+withMaybeStorable Nothing f=f nullPtr
+withMaybeStorable (Just x) f=withStorable x f
+
+withStorable :: Storable a => a -> (Ptr a -> IO b) -> IO b
+withStorable x f=alloca (\ptr->poke ptr x>> f ptr)
+
+withMaybeCString :: Maybe String -> (CString -> IO a) -> IO a
+withMaybeCString Nothing f=f nullPtr
+withMaybeCString (Just s) f=withCString s f
+
diff --git a/pulse-simple.cabal b/pulse-simple.cabal
new file mode 100644
--- /dev/null
+++ b/pulse-simple.cabal
@@ -0,0 +1,22 @@
+Name:            pulse-simple
+Cabal-Version:   >=1.2
+Version:         0.1.11
+Author:          Daiki Handa
+Maintainer:      xanxys@gmail.com
+Synopsis:        binding to Simple API of pulseaudio
+Build-Type:      Simple
+License:         BSD3
+License-File:    LICENSE
+Category:        Sound
+Description:
+  Binding to simple version of client API for the pulseaudio soundserver.
+  Although it does not provide advanced features and some not-so-adavanced features like
+  volume control, it should be enough for simple applications.
+  Tested only on 64-bit linux with ghc-6.10.3.
+
+Library
+    Extensions: ForeignFunctionInterface
+    Extra-Libraries: pulse-simple
+    Build-depends:   base>=3 && <4, bytestring
+    Exposed-Modules: Sound.Pulse.Simple
+
