osc (empty) → 1.0.0.2
raw patch · 6 files changed
+250/−0 lines, 6 filesdep +attoparsecdep +basedep +binarysetup-changed
Dependencies added: attoparsec, base, binary, bytestring, data-binary-ieee754, network
Files
- LICENSE +24/−0
- Setup.hs +6/−0
- osc.cabal +41/−0
- src/Sound/OSC.hs +44/−0
- src/Sound/OSC/Parser.hs +111/−0
- src/Sound/OSC/Printer.hs +24/−0
+ LICENSE view
@@ -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.
+ Setup.hs view
@@ -0,0 +1,6 @@+module Main (main) where++import Distribution.Simple++main :: IO ()+main = defaultMain
+ osc.cabal view
@@ -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+ +
+ src/Sound/OSC.hs view
@@ -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)
+ src/Sound/OSC/Parser.hs view
@@ -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
+ src/Sound/OSC/Printer.hs view
@@ -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