diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,24 @@
+Copyright 2010, Simon Marlow
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+ 
+- 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.
+ 
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND THE CONTRIBUTORS "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 OR THE
+CONTRIBUTORS 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,6 @@
+module Main (main) where
+
+import Distribution.Simple
+
+main :: IO ()
+main = defaultMain
diff --git a/osc.cabal b/osc.cabal
new file mode 100644
--- /dev/null
+++ b/osc.cabal
@@ -0,0 +1,41 @@
+name: osc
+version: 1.0.0.2
+cabal-version: >=1.6
+build-type: Simple
+license: BSD3
+license-file: LICENSE
+copyright: (c) Gabriel Pickl
+maintainer: Gabriel Pickl <peacemotion@gmail.com>
+stability: unstable
+homepage: https://github.com/peacememories/haskell-osc
+bug-reports: mailto:peacemotion@gmail.com
+synopsis: A library to handle messages in the OSC protocol
+description: This library allows users to parse and write OSC (Open Sound Control) messages.
+             It uses the parsing library attoparsec to read binary data.
+category: Sound
+author: Gabriel Pickl
+data-dir: ""
+ 
+source-repository head
+    type: git
+    location: https://github.com/peacememories/haskell-osc.git
+ 
+flag threaded
+    Default: False
+ 
+library
+    build-depends: base >=4.2 && <5, attoparsec ==0.12.*,
+                   binary ==0.7.*, bytestring ==0.10.*, data-binary-ieee754 ==0.4.*,
+                   network ==2.6.*
+     
+    if flag(threaded)
+        exposed: True
+        buildable: True
+        ghc-options: -threaded
+    exposed-modules: Sound.OSC Sound.OSC.Parser
+    exposed: True
+    buildable: True
+    hs-source-dirs: src
+    other-modules: Sound.OSC.Printer
+ 
+ 
diff --git a/src/Sound/OSC.hs b/src/Sound/OSC.hs
new file mode 100644
--- /dev/null
+++ b/src/Sound/OSC.hs
@@ -0,0 +1,44 @@
+-----------------------------------------------------------------------------
+--
+-- Module      :  Sound.OSC
+-- Copyright   :  (c) Gabriel Pickl
+-- License     :  BSD3
+--
+-- Maintainer  :  Gabriel Pickl <peacemotion@gmail.com>
+-- Stability   :  unstable
+-- Portability :
+--
+-- |
+--
+-----------------------------------------------------------------------------
+
+module Sound.OSC
+    ( Timestamp
+    , OSC
+        ( Bundle
+        , Message
+        )
+    , Datum
+        ( String
+        , Int
+        , Float
+        , Blob
+        )
+) where
+
+import Data.Word       (Word64)
+import Data.Int        (Int32)
+import Data.ByteString (ByteString)
+
+type Timestamp = Word64
+
+data OSC = Bundle Timestamp [OSC]
+         | Message String [Datum]
+         deriving (Show)
+
+-- Minimal type definition for OSC
+data Datum = String String
+           | Int    Int32
+           | Float  Float
+           | Blob   ByteString
+           deriving (Show)
diff --git a/src/Sound/OSC/Parser.hs b/src/Sound/OSC/Parser.hs
new file mode 100644
--- /dev/null
+++ b/src/Sound/OSC/Parser.hs
@@ -0,0 +1,111 @@
+-----------------------------------------------------------------------------
+--
+-- Module      :  Sound.OSC.Parser
+-- Copyright   :  (c) Gabriel Pickl
+-- License     :  BSD3
+--
+-- Maintainer  :  Gabriel Pickl <peacemotion@gmail.com>
+-- Stability   :  unstable
+-- Portability :
+--
+-- |
+--
+-----------------------------------------------------------------------------
+
+module Sound.OSC.Parser (
+    osc
+) where
+
+{-# LANGUAGE DoAndIfThenElse #-}
+
+
+import Data.Attoparsec.ByteString as AP
+import Data.Binary.Get
+import Data.Binary.IEEE754
+import Data.Word (Word64, Word8)
+import Control.Applicative ((<$>), (<|>))
+import Data.ByteString.Char8 (unpack, pack)
+import Data.Int (Int32)
+import qualified Data.ByteString as BS
+import Data.ByteString.Lazy (fromStrict)
+import Data.ByteString (ByteString)
+
+import Sound.OSC
+
+nest :: AP.Parser ByteString -> AP.Parser a -> AP.Parser a
+nest bsp p = bsp >>= parse
+    where
+        parse bs = either fail return (parseOnly p bs)
+
+int32 :: AP.Parser Int32
+int32 = convert <$> AP.take 4
+    where
+        convert :: ByteString -> Int32
+        convert bs = fromIntegral $ runGet getWord32be $ fromStrict bs
+
+float32 :: AP.Parser Float
+float32 = convert <$> AP.take 4
+    where
+        convert :: ByteString -> Float
+        convert bs = runGet getFloat32be $ fromStrict bs
+
+timestamp :: AP.Parser Timestamp
+timestamp = convert <$> AP.take 8
+    where
+        convert :: ByteString -> Timestamp
+        convert bs = runGet getWord64be $ fromStrict bs
+
+oscString :: AP.Parser ByteString
+oscString = do
+    str <- AP.takeTill (==0)
+    AP.take $ blockPadding (BS.length str)
+    return str
+    where
+        blockPadding len = ((-len-1) `mod` 4)+1
+
+tokenParser :: Word8 -> AP.Parser Datum
+-- s
+tokenParser 115 = String . unpack <$> oscString
+-- i
+tokenParser 105 = Int <$> int32
+-- f
+tokenParser 102 = Float <$> float32
+-- b
+tokenParser 98 = do
+    size <- int32
+    Blob <$> (AP.take $ fromIntegral size)
+tokenParser t = fail $ "Could not parse type " ++ show t
+
+typeTag :: Parser [Word8]
+typeTag = do
+    first <- AP.peekWord8
+    case first of
+        Just 44 -> tail . BS.unpack <$> oscString
+        Just other -> fail $ "Unexpected token: " ++ show other
+        Nothing -> return []
+
+message :: AP.Parser OSC
+message = do
+    addr <- unpack <$> oscString
+    types <- typeTag
+    (Message addr) <$> (sequence $ map tokenParser types)
+
+bundle :: AP.Parser OSC
+bundle = do
+    string $ pack "#bundle"
+    word8 0
+    time <- timestamp
+    elems <- AP.manyTill bundleElement AP.endOfInput
+    return $ Bundle time elems
+
+bundleElement :: AP.Parser OSC
+bundleElement = do
+    length <- int32
+    nest (AP.take $ fromIntegral length) osc
+
+osc :: AP.Parser OSC
+osc = do
+    first <- AP.peekWord8
+    case first of
+        Just 35 -> bundle
+        otherwise -> message
diff --git a/src/Sound/OSC/Printer.hs b/src/Sound/OSC/Printer.hs
new file mode 100644
--- /dev/null
+++ b/src/Sound/OSC/Printer.hs
@@ -0,0 +1,24 @@
+-----------------------------------------------------------------------------
+--
+-- Module      :  Sound.OSC.Printer
+-- Copyright   :  (c) Gabriel Pickl
+-- License     :  BSD3
+--
+-- Maintainer  :  Gabriel Pickl <peacemotion@gmail.com>
+-- Stability   :  unstable
+-- Portability :
+--
+-- |
+--
+-----------------------------------------------------------------------------
+
+module Sound.OSC.Printer (
+    printOSC
+) where
+
+import Sound.OSC
+
+import Data.ByteString (ByteString)
+
+printOSC :: OSC -> ByteString
+printOSC = undefined
