packages feed

tidal-vis-1.0.14: src/Realtime/Types.hs

module Realtime.Types
       ( TidalPacket (..)
       , ColorI
       , defaultTidalPacket
       , packetToTidalPacket
       , parsePacket
       ) where

import Data.Bits (shiftR, (.&.))
import Data.Hashable (hash)
import Data.Maybe (fromMaybe)
import Sound.OSC


data TidalPacket = TidalPacket
    { tpTime  :: Double
    , tpCycle :: Float
    , tpDelta :: Float
    , tpColor :: ColorI
    } deriving (Eq, Show)

type ColorI = (Int, Int, Int, Int)

defaultTidalPacket :: TidalPacket
defaultTidalPacket = TidalPacket
    { tpTime = immediately
    , tpCycle = 1.0
    , tpDelta = 1.0
    , tpColor = (100, 200, 50, 250)
    }

parsePacket :: Packet -> Maybe (Int,Int,Int,Int)
parsePacket p = tupleI list
  where
    list = mapM datum_integral . messageDatum =<< packet_to_message p
    tupleI = \case
        Nothing -> Nothing
        Just list' -> case list' of
            (r:g:b:a:_) -> Just (r,g,b,a)
            _           -> Nothing

stringToColour :: String -> (Int,Int,Int,Int)
stringToColour str = (r, g, b, 250)
  where
    i = hash str `mod` 16777216
    r = (i .&. 0xFF0000) `shiftR` 16
    g = (i .&. 0x00FF00) `shiftR` 8
    b = i .&. 0x0000FF

deleteDatumValue :: String -> [Datum] -> [Datum]
deleteDatumValue d ds = go
  where
    go = case break (==d') ds of
        (f,x:_:xs) -> f ++ (x:xs)
        _          -> []
    d' = string d

roundFloats :: Datum -> Datum
roundFloats = \case
    Float d_float -> Float (fromInteger (round $ d_float * 10000) / 10000)
    x -> x

takeDatumValue :: String -> [Datum] -> Datum
takeDatumValue d ds = go
  where
    go = case break (== d') ds of
      (_,_:v:_) -> v
      _         -> string "No value for your datum"
    d' = string d

packetToTidalPacket :: Packet -> TidalPacket
packetToTidalPacket p = TidalPacket
    { tpTime = bundleTime bund
    , tpCycle = cycle'
    , tpDelta = delta'
    , tpColor = color'
    }
  where
    bund = packet_to_bundle p
    datums = concatMap messageDatum $ bundleMessages bund
    cycle' = takeFloat "cycle" datums
    delta' = takeFloat "delta" datums
    color' = stringToColour $ show $ deleteDatumValue "cycle" datums
    takeFloat str = fromMaybe 0 . datum_floating . roundFloats . takeDatumValue str