{-# LANGUAGE ScopedTypeVariables #-} module Sound.Tidal.EspGrid (tidalEspGridLink,cpsEsp,espgrid) where import Control.Concurrent.MVar import Control.Concurrent (forkIO,threadDelay) import Control.Monad (forever) import Control.Exception import Sound.OSC.FD import Sound.Tidal.Tempo import Sound.Tidal.Stream (Stream, sTempoMV) parseEspTempo :: [Datum] -> Maybe (Tempo -> Tempo) parseEspTempo :: [Datum] -> Maybe (Tempo -> Tempo) parseEspTempo d :: [Datum] d = do Integer on :: Integer <- Datum -> Maybe Integer forall i. Integral i => Datum -> Maybe i datum_integral ([Datum] d[Datum] -> Int -> Datum forall a. [a] -> Int -> a !!0) Time bpm <- Datum -> Maybe Time forall n. Floating n => Datum -> Maybe n datum_floating ([Datum] d[Datum] -> Int -> Datum forall a. [a] -> Int -> a !!1) Integer t1 :: Integer <- Datum -> Maybe Integer forall i. Integral i => Datum -> Maybe i datum_integral ([Datum] d[Datum] -> Int -> Datum forall a. [a] -> Int -> a !!2) Integer t2 <- Datum -> Maybe Integer forall i. Integral i => Datum -> Maybe i datum_integral ([Datum] d[Datum] -> Int -> Datum forall a. [a] -> Int -> a !!3) Integer n :: Integer <- Datum -> Maybe Integer forall i. Integral i => Datum -> Maybe i datum_integral ([Datum] d[Datum] -> Int -> Datum forall a. [a] -> Int -> a !!4) let nanos :: Integer nanos = (Integer t1Integer -> Integer -> Integer forall a. Num a => a -> a -> a *1000000000) Integer -> Integer -> Integer forall a. Num a => a -> a -> a + Integer t2 (Tempo -> Tempo) -> Maybe (Tempo -> Tempo) forall (m :: * -> *) a. Monad m => a -> m a return ((Tempo -> Tempo) -> Maybe (Tempo -> Tempo)) -> (Tempo -> Tempo) -> Maybe (Tempo -> Tempo) forall a b. (a -> b) -> a -> b $ \t :: Tempo t -> Tempo t { atTime :: Time atTime = Time -> Time forall n. Num n => n -> n ut_to_ntpr (Time -> Time) -> Time -> Time forall a b. (a -> b) -> a -> b $ Integer -> Time forall a b. (Real a, Fractional b) => a -> b realToFrac Integer nanos Time -> Time -> Time forall a. Fractional a => a -> a -> a / 1000000000, atCycle :: Rational atCycle = Integer -> Rational forall a b. (Integral a, Num b) => a -> b fromIntegral Integer n, cps :: Time cps = Time bpmTime -> Time -> Time forall a. Fractional a => a -> a -> a /60, paused :: Bool paused = Integer on Integer -> Integer -> Bool forall a. Eq a => a -> a -> Bool == 0 } changeTempo :: MVar Tempo -> Packet -> IO () changeTempo :: MVar Tempo -> Packet -> IO () changeTempo t :: MVar Tempo t (Packet_Message msg :: Message msg) = case [Datum] -> Maybe (Tempo -> Tempo) parseEspTempo (Message -> [Datum] messageDatum Message msg) of Just f :: Tempo -> Tempo f -> MVar Tempo -> (Tempo -> IO Tempo) -> IO () forall a. MVar a -> (a -> IO a) -> IO () modifyMVarMasked_ MVar Tempo t ((Tempo -> IO Tempo) -> IO ()) -> (Tempo -> IO Tempo) -> IO () forall a b. (a -> b) -> a -> b $ \t0 :: Tempo t0 -> Tempo -> IO Tempo forall (m :: * -> *) a. Monad m => a -> m a return (Tempo -> Tempo f Tempo t0) Nothing -> String -> IO () putStrLn "Warning: Unable to parse message from EspGrid as Tempo" changeTempo _ _ = String -> IO () putStrLn "Serious error: Can only process Packet_Message" tidalEspGridLink :: MVar Tempo -> IO () tidalEspGridLink :: MVar Tempo -> IO () tidalEspGridLink _ = String -> IO () putStrLn "Function no longer supported, please use 'espgrid tidal' to connect to ESPgrid instead." espgrid :: Stream -> IO () espgrid :: Stream -> IO () espgrid st :: Stream st = do let t :: MVar Tempo t = Stream -> MVar Tempo sTempoMV Stream st UDP socket <- String -> Int -> IO UDP openUDP "127.0.0.1" 5510 ThreadId _ <- IO () -> IO ThreadId forkIO (IO () -> IO ThreadId) -> IO () -> IO ThreadId forall a b. (a -> b) -> a -> b $ IO () -> IO () forall (f :: * -> *) a b. Applicative f => f a -> f b forever (IO () -> IO ()) -> IO () -> IO () forall a b. (a -> b) -> a -> b $ do (do UDP -> Message -> IO () forall t. Transport t => t -> Message -> IO () sendMessage UDP socket (Message -> IO ()) -> Message -> IO () forall a b. (a -> b) -> a -> b $ String -> [Datum] -> Message Message "/esp/tempo/q" [] Packet response <- UDP -> String -> IO Packet forall t. Transport t => t -> String -> IO Packet waitAddress UDP socket "/esp/tempo/r" MVar Tempo -> Packet -> IO () Sound.Tidal.EspGrid.changeTempo MVar Tempo t Packet response Int -> IO () threadDelay 200000) IO () -> (SomeException -> IO ()) -> IO () forall e a. Exception e => IO a -> (e -> IO a) -> IO a `catch` (\e :: SomeException e -> String -> IO () putStrLn (String -> IO ()) -> String -> IO () forall a b. (a -> b) -> a -> b $ "exception caught in tidalEspGridLink: " String -> String -> String forall a. [a] -> [a] -> [a] ++ SomeException -> String forall a. Show a => a -> String show (SomeException e :: SomeException)) () -> IO () forall (m :: * -> *) a. Monad m => a -> m a return () cpsEsp :: Real t => t -> IO () cpsEsp :: t -> IO () cpsEsp t :: t t = do UDP socket <- String -> Int -> IO UDP openUDP "127.0.0.1" 5510 UDP -> Message -> IO () forall t. Transport t => t -> Message -> IO () sendMessage UDP socket (Message -> IO ()) -> Message -> IO () forall a b. (a -> b) -> a -> b $ String -> [Datum] -> Message Message "/esp/beat/tempo" [t -> Datum forall n. Real n => n -> Datum float (t tt -> t -> t forall a. Num a => a -> a -> a *60)]