packages feed

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

module Realtime.Server
       ( animeCollectorServerU
       ) where

import Control.Concurrent
import Control.Concurrent.Async (race_)
import Control.Concurrent.Chan.Unagi.Bounded (InChan, OutChan)
import Control.Monad
import Sound.OSC

import qualified Control.Concurrent.Chan.Unagi.Bounded as U
import qualified Sound.OSC.FD as FD

import Realtime.Animation (movingPatterns)
import Realtime.Types (ColorI, TidalPacket (..), packetToTidalPacket)


-- Command to start the server in a repl for testing
-- do u <- t0; udp_close u; hoscServerTPU

animeCollectorServerU :: IO ()
animeCollectorServerU = do
    (inChan, outChan) <- U.newChan 100
    mvar <- newEmptyMVar
    race_ (hoscServerTPU inChan) $ race_ (collector outChan mvar) (movingPatterns mvar)

t0 :: IO UDP
t0 = udpServer "127.0.0.1" 5050

-- Listen to osc packets and write them to channel.
hoscServerTPU :: InChan TidalPacket -> IO ()
hoscServerTPU inChan = FD.withTransport t0 $ \udp -> forever $ do
    packet <- udp_recv_packet udp
    let tp = packetToTidalPacket packet
    U.writeChan inChan tp

-- Collect sync packets to list and put mvar for animation.
collector :: OutChan TidalPacket -> MVar [ColorI] -> IO ()
collector outChan mvColors = do
    buffer <- newEmptyMVar
    forever $ do
        c <- U.readChan outChan
        mtp <- tryTakeMVar buffer
        case mtp of
            Nothing -> putMVar buffer (tpTime c, [tpColor c])
            Just tp ->
                if fst tp == tpTime c
                then void $ putMVar buffer (toTuple c tp)
                else do
                    putMVar buffer (tpTime c, [tpColor c])
                    putMVar mvColors $ snd tp

-- Take time and color.
toTuple :: TidalPacket -> (Double, [ColorI]) -> (Double, [ColorI])
toTuple tp (f,tps) = (f, tpColor tp : tps)