{-# LANGUAGE ConstraintKinds, GeneralizedNewtypeDeriving, FlexibleContexts, ScopedTypeVariables, BangPatterns #-}
{-# OPTIONS_GHC -fno-warn-missing-fields #-}
{-# language DeriveGeneric, StandaloneDeriving #-}
module Sound.Tidal.Stream (module Sound.Tidal.Stream) where
import Control.Applicative ((<|>))
import Control.Concurrent.MVar
import Control.Concurrent
import Control.Monad (forM_, when)
import Data.Coerce (coerce)
import qualified Data.Map.Strict as Map
import Data.Maybe (fromJust, fromMaybe, catMaybes, isJust)
import qualified Control.Exception as E
import Foreign
import Foreign.C.Types
import System.IO (hPutStrLn, stderr)
import qualified Sound.Osc.Fd as O
import qualified Sound.Osc.Time.Timeout as O
import qualified Network.Socket as N
import Sound.Tidal.Config
import Sound.Tidal.Core (stack, (#))
import Sound.Tidal.ID
import qualified Sound.Tidal.Link as Link
import Sound.Tidal.Params (pS)
import Sound.Tidal.Pattern
import qualified Sound.Tidal.Tempo as T
import Sound.Tidal.Utils ((!!!))
import Data.List (sortOn)
import System.Random (getStdRandom, randomR)
import Sound.Tidal.Show ()
import Sound.Tidal.Version
import Sound.Tidal.StreamTypes as Sound.Tidal.Stream
data Stream = Stream {Stream -> Config
sConfig :: Config,
Stream -> MVar [Int]
sBusses :: MVar [Int],
Stream -> MVar ValueMap
sStateMV :: MVar ValueMap,
Stream -> AbletonLink
sLink :: Link.AbletonLink,
Stream -> Maybe Udp
sListen :: Maybe O.Udp,
Stream -> MVar PlayMap
sPMapMV :: MVar PlayMap,
Stream -> MVar [TempoAction]
sActionsMV :: MVar [T.TempoAction],
Stream -> MVar (ControlPattern -> ControlPattern)
sGlobalFMV :: MVar (ControlPattern -> ControlPattern),
Stream -> [Cx]
sCxs :: [Cx]
}
data Cx = Cx {Cx -> Target
cxTarget :: Target,
Cx -> Udp
cxUDP :: O.Udp,
Cx -> [OSC]
cxOSCs :: [OSC],
Cx -> AddrInfo
cxAddr :: N.AddrInfo,
Cx -> Maybe AddrInfo
cxBusAddr :: Maybe N.AddrInfo
}
deriving (Int -> Cx -> ShowS
[Cx] -> ShowS
Cx -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Cx] -> ShowS
$cshowList :: [Cx] -> ShowS
show :: Cx -> String
$cshow :: Cx -> String
showsPrec :: Int -> Cx -> ShowS
$cshowsPrec :: Int -> Cx -> ShowS
Show)
data StampStyle = BundleStamp
| MessageStamp
deriving (StampStyle -> StampStyle -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: StampStyle -> StampStyle -> Bool
$c/= :: StampStyle -> StampStyle -> Bool
== :: StampStyle -> StampStyle -> Bool
$c== :: StampStyle -> StampStyle -> Bool
Eq, Int -> StampStyle -> ShowS
[StampStyle] -> ShowS
StampStyle -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [StampStyle] -> ShowS
$cshowList :: [StampStyle] -> ShowS
show :: StampStyle -> String
$cshow :: StampStyle -> String
showsPrec :: Int -> StampStyle -> ShowS
$cshowsPrec :: Int -> StampStyle -> ShowS
Show)
data Schedule = Pre StampStyle
| Live
deriving (Schedule -> Schedule -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Schedule -> Schedule -> Bool
$c/= :: Schedule -> Schedule -> Bool
== :: Schedule -> Schedule -> Bool
$c== :: Schedule -> Schedule -> Bool
Eq, Int -> Schedule -> ShowS
[Schedule] -> ShowS
Schedule -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Schedule] -> ShowS
$cshowList :: [Schedule] -> ShowS
show :: Schedule -> String
$cshow :: Schedule -> String
showsPrec :: Int -> Schedule -> ShowS
$cshowsPrec :: Int -> Schedule -> ShowS
Show)
data Target = Target {Target -> String
oName :: String,
Target -> String
oAddress :: String,
Target -> Int
oPort :: Int,
Target -> Maybe Int
oBusPort :: Maybe Int,
Target -> Double
oLatency :: Double,
Target -> Maybe Arc
oWindow :: Maybe Arc,
Target -> Schedule
oSchedule :: Schedule,
Target -> Bool
oHandshake :: Bool
}
deriving Int -> Target -> ShowS
[Target] -> ShowS
Target -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Target] -> ShowS
$cshowList :: [Target] -> ShowS
show :: Target -> String
$cshow :: Target -> String
showsPrec :: Int -> Target -> ShowS
$cshowsPrec :: Int -> Target -> ShowS
Show
data Args = Named {Args -> [String]
requiredArgs :: [String]}
| ArgList [(String, Maybe Value)]
deriving Int -> Args -> ShowS
[Args] -> ShowS
Args -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Args] -> ShowS
$cshowList :: [Args] -> ShowS
show :: Args -> String
$cshow :: Args -> String
showsPrec :: Int -> Args -> ShowS
$cshowsPrec :: Int -> Args -> ShowS
Show
data OSC = OSC {OSC -> String
path :: String,
OSC -> Args
args :: Args
}
| OSCContext {path :: String}
deriving Int -> OSC -> ShowS
[OSC] -> ShowS
OSC -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [OSC] -> ShowS
$cshowList :: [OSC] -> ShowS
show :: OSC -> String
$cshow :: OSC -> String
showsPrec :: Int -> OSC -> ShowS
$cshowsPrec :: Int -> OSC -> ShowS
Show
data ProcessedEvent =
ProcessedEvent {
ProcessedEvent -> Bool
peHasOnset :: Bool,
ProcessedEvent -> Event ValueMap
peEvent :: Event ValueMap,
ProcessedEvent -> Beat
peCps :: Link.BPM,
ProcessedEvent -> Micros
peDelta :: Link.Micros,
ProcessedEvent -> Rational
peCycle :: Time,
ProcessedEvent -> Micros
peOnWholeOrPart :: Link.Micros,
ProcessedEvent -> Double
peOnWholeOrPartOsc :: O.Time,
ProcessedEvent -> Micros
peOnPart :: Link.Micros,
ProcessedEvent -> Double
peOnPartOsc :: O.Time
}
sDefault :: String -> Maybe Value
sDefault :: String -> Maybe Value
sDefault String
x = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ String -> Value
VS String
x
fDefault :: Double -> Maybe Value
fDefault :: Double -> Maybe Value
fDefault Double
x = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ Double -> Value
VF Double
x
rDefault :: Rational -> Maybe Value
rDefault :: Rational -> Maybe Value
rDefault Rational
x = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ Rational -> Value
VR Rational
x
iDefault :: Int -> Maybe Value
iDefault :: Int -> Maybe Value
iDefault Int
x = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ Int -> Value
VI Int
x
bDefault :: Bool -> Maybe Value
bDefault :: Bool -> Maybe Value
bDefault Bool
x = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ Bool -> Value
VB Bool
x
xDefault :: [Word8] -> Maybe Value
xDefault :: [Word8] -> Maybe Value
xDefault [Word8]
x = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ [Word8] -> Value
VX [Word8]
x
required :: Maybe Value
required :: Maybe Value
required = forall a. Maybe a
Nothing
superdirtTarget :: Target
superdirtTarget :: Target
superdirtTarget = Target {oName :: String
oName = String
"SuperDirt",
oAddress :: String
oAddress = String
"127.0.0.1",
oPort :: Int
oPort = Int
57120,
oBusPort :: Maybe Int
oBusPort = forall a. a -> Maybe a
Just Int
57110,
oLatency :: Double
oLatency = Double
0.2,
oWindow :: Maybe Arc
oWindow = forall a. Maybe a
Nothing,
oSchedule :: Schedule
oSchedule = StampStyle -> Schedule
Pre StampStyle
BundleStamp,
oHandshake :: Bool
oHandshake = Bool
True
}
superdirtShape :: OSC
superdirtShape :: OSC
superdirtShape = String -> Args -> OSC
OSC String
"/dirt/play" forall a b. (a -> b) -> a -> b
$ Named {requiredArgs :: [String]
requiredArgs = [String
"s"]}
dirtTarget :: Target
dirtTarget :: Target
dirtTarget = Target {oName :: String
oName = String
"Dirt",
oAddress :: String
oAddress = String
"127.0.0.1",
oPort :: Int
oPort = Int
7771,
oBusPort :: Maybe Int
oBusPort = forall a. Maybe a
Nothing,
oLatency :: Double
oLatency = Double
0.02,
oWindow :: Maybe Arc
oWindow = forall a. Maybe a
Nothing,
oSchedule :: Schedule
oSchedule = StampStyle -> Schedule
Pre StampStyle
MessageStamp,
oHandshake :: Bool
oHandshake = Bool
False
}
dirtShape :: OSC
dirtShape :: OSC
dirtShape = String -> Args -> OSC
OSC String
"/play" forall a b. (a -> b) -> a -> b
$ [(String, Maybe Value)] -> Args
ArgList [(String
"cps", Double -> Maybe Value
fDefault Double
0),
(String
"s", Maybe Value
required),
(String
"offset", Double -> Maybe Value
fDefault Double
0),
(String
"begin", Double -> Maybe Value
fDefault Double
0),
(String
"end", Double -> Maybe Value
fDefault Double
1),
(String
"speed", Double -> Maybe Value
fDefault Double
1),
(String
"pan", Double -> Maybe Value
fDefault Double
0.5),
(String
"velocity", Double -> Maybe Value
fDefault Double
0.5),
(String
"vowel", String -> Maybe Value
sDefault String
""),
(String
"cutoff", Double -> Maybe Value
fDefault Double
0),
(String
"resonance", Double -> Maybe Value
fDefault Double
0),
(String
"accelerate", Double -> Maybe Value
fDefault Double
0),
(String
"shape", Double -> Maybe Value
fDefault Double
0),
(String
"kriole", Int -> Maybe Value
iDefault Int
0),
(String
"gain", Double -> Maybe Value
fDefault Double
1),
(String
"cut", Int -> Maybe Value
iDefault Int
0),
(String
"delay", Double -> Maybe Value
fDefault Double
0),
(String
"delaytime", Double -> Maybe Value
fDefault (-Double
1)),
(String
"delayfeedback", Double -> Maybe Value
fDefault (-Double
1)),
(String
"crush", Double -> Maybe Value
fDefault Double
0),
(String
"coarse", Int -> Maybe Value
iDefault Int
0),
(String
"hcutoff", Double -> Maybe Value
fDefault Double
0),
(String
"hresonance", Double -> Maybe Value
fDefault Double
0),
(String
"bandf", Double -> Maybe Value
fDefault Double
0),
(String
"bandq", Double -> Maybe Value
fDefault Double
0),
(String
"unit", String -> Maybe Value
sDefault String
"rate"),
(String
"loop", Double -> Maybe Value
fDefault Double
0),
(String
"n", Double -> Maybe Value
fDefault Double
0),
(String
"attack", Double -> Maybe Value
fDefault (-Double
1)),
(String
"hold", Double -> Maybe Value
fDefault Double
0),
(String
"release", Double -> Maybe Value
fDefault (-Double
1)),
(String
"orbit", Int -> Maybe Value
iDefault Int
0)
]
defaultCps :: O.Time
defaultCps :: Double
defaultCps = Double
0.5625
startStream :: Config -> [(Target, [OSC])] -> IO Stream
startStream :: Config -> [(Target, [OSC])] -> IO Stream
startStream Config
config [(Target, [OSC])]
oscmap
= do MVar ValueMap
sMapMV <- forall a. a -> IO (MVar a)
newMVar forall k a. Map k a
Map.empty
MVar PlayMap
pMapMV <- forall a. a -> IO (MVar a)
newMVar forall k a. Map k a
Map.empty
MVar [Int]
bussesMV <- forall a. a -> IO (MVar a)
newMVar []
MVar (ControlPattern -> ControlPattern)
globalFMV <- forall a. a -> IO (MVar a)
newMVar forall a. a -> a
id
MVar [TempoAction]
actionsMV <- forall a. IO (MVar a)
newEmptyMVar
IO String
tidal_status_string forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Config -> String -> IO ()
verbose Config
config
Config -> String -> IO ()
verbose Config
config forall a b. (a -> b) -> a -> b
$ String
"Listening for external controls on " forall a. [a] -> [a] -> [a]
++ Config -> String
cCtrlAddr Config
config forall a. [a] -> [a] -> [a]
++ String
":" forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show (Config -> Int
cCtrlPort Config
config)
Maybe Udp
listen <- Config -> IO (Maybe Udp)
openListener Config
config
[Cx]
cxs <- forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (\(Target
target, [OSC]
os) -> do AddrInfo
remote_addr <- String -> String -> IO AddrInfo
resolve (Target -> String
oAddress Target
target) (forall a. Show a => a -> String
show forall a b. (a -> b) -> a -> b
$ Target -> Int
oPort Target
target)
Maybe AddrInfo
remote_bus_addr <- if forall a. Maybe a -> Bool
isJust forall a b. (a -> b) -> a -> b
$ Target -> Maybe Int
oBusPort Target
target
then forall a. a -> Maybe a
Just forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> String -> IO AddrInfo
resolve (Target -> String
oAddress Target
target) (forall a. Show a => a -> String
show forall a b. (a -> b) -> a -> b
$ forall a. HasCallStack => Maybe a -> a
fromJust forall a b. (a -> b) -> a -> b
$ Target -> Maybe Int
oBusPort Target
target)
else forall (m :: * -> *) a. Monad m => a -> m a
return forall a. Maybe a
Nothing
let broadcast :: Int
broadcast = if Config -> Bool
cCtrlBroadcast Config
config then Int
1 else Int
0
Udp
u <- (Socket -> SockAddr -> IO ()) -> String -> Int -> IO Udp
O.udp_socket (\Socket
sock SockAddr
sockaddr -> do Socket -> SocketOption -> Int -> IO ()
N.setSocketOption Socket
sock SocketOption
N.Broadcast Int
broadcast
Socket -> SockAddr -> IO ()
N.connect Socket
sock SockAddr
sockaddr
) (Target -> String
oAddress Target
target) (Target -> Int
oPort Target
target)
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Cx {cxUDP :: Udp
cxUDP = Udp
u, cxAddr :: AddrInfo
cxAddr = AddrInfo
remote_addr, cxBusAddr :: Maybe AddrInfo
cxBusAddr = Maybe AddrInfo
remote_bus_addr, cxTarget :: Target
cxTarget = Target
target, cxOSCs :: [OSC]
cxOSCs = [OSC]
os}
) [(Target, [OSC])]
oscmap
let bpm :: Beat
bpm = (coerce :: forall a b. Coercible a b => a -> b
coerce Double
defaultCps) forall a. Num a => a -> a -> a
* Beat
60 forall a. Num a => a -> a -> a
* (Config -> Beat
cBeatsPerCycle Config
config)
AbletonLink
abletonLink <- Beat -> IO AbletonLink
Link.create Beat
bpm
let stream :: Stream
stream = Stream {sConfig :: Config
sConfig = Config
config,
sBusses :: MVar [Int]
sBusses = MVar [Int]
bussesMV,
sStateMV :: MVar ValueMap
sStateMV = MVar ValueMap
sMapMV,
sLink :: AbletonLink
sLink = AbletonLink
abletonLink,
sListen :: Maybe Udp
sListen = Maybe Udp
listen,
sPMapMV :: MVar PlayMap
sPMapMV = MVar PlayMap
pMapMV,
sActionsMV :: MVar [TempoAction]
sActionsMV = MVar [TempoAction]
actionsMV,
sGlobalFMV :: MVar (ControlPattern -> ControlPattern)
sGlobalFMV = MVar (ControlPattern -> ControlPattern)
globalFMV,
sCxs :: [Cx]
sCxs = [Cx]
cxs
}
Stream -> IO ()
sendHandshakes Stream
stream
let ac :: ActionHandler
ac = T.ActionHandler {
onTick :: TickState -> LinkOperations -> ValueMap -> IO ValueMap
T.onTick = Stream -> TickState -> LinkOperations -> ValueMap -> IO ValueMap
onTick Stream
stream,
onSingleTick :: LinkOperations -> ValueMap -> ControlPattern -> IO ValueMap
T.onSingleTick = Stream
-> LinkOperations -> ValueMap -> ControlPattern -> IO ValueMap
onSingleTick Stream
stream,
updatePattern :: ID -> Rational -> ControlPattern -> IO ()
T.updatePattern = Stream -> ID -> Rational -> ControlPattern -> IO ()
updatePattern Stream
stream
}
[ThreadId]
_ <- Config
-> MVar ValueMap
-> MVar PlayMap
-> MVar [TempoAction]
-> ActionHandler
-> AbletonLink
-> IO [ThreadId]
T.clocked Config
config MVar ValueMap
sMapMV MVar PlayMap
pMapMV MVar [TempoAction]
actionsMV ActionHandler
ac AbletonLink
abletonLink
ThreadId
_ <- IO () -> IO ThreadId
forkIO forall a b. (a -> b) -> a -> b
$ Int -> Config -> Stream -> IO ()
ctrlResponder Int
0 Config
config Stream
stream
forall (m :: * -> *) a. Monad m => a -> m a
return Stream
stream
sendHandshakes :: Stream -> IO ()
sendHandshakes :: Stream -> IO ()
sendHandshakes Stream
stream = forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ Cx -> IO ()
sendHandshake forall a b. (a -> b) -> a -> b
$ forall a. (a -> Bool) -> [a] -> [a]
filter (Target -> Bool
oHandshake forall b c a. (b -> c) -> (a -> b) -> a -> c
. Cx -> Target
cxTarget) (Stream -> [Cx]
sCxs Stream
stream)
where sendHandshake :: Cx -> IO ()
sendHandshake Cx
cx = if (forall a. Maybe a -> Bool
isJust forall a b. (a -> b) -> a -> b
$ Stream -> Maybe Udp
sListen Stream
stream)
then
do
Bool -> Maybe Udp -> Cx -> Message -> IO ()
sendO Bool
False (Stream -> Maybe Udp
sListen Stream
stream) Cx
cx forall a b. (a -> b) -> a -> b
$ String -> [Datum] -> Message
O.Message String
"/dirt/handshake" []
else
Handle -> String -> IO ()
hPutStrLn Handle
stderr String
"Can't handshake with SuperCollider without control port."
sendO :: Bool -> (Maybe O.Udp) -> Cx -> O.Message -> IO ()
sendO :: Bool -> Maybe Udp -> Cx -> Message -> IO ()
sendO Bool
isBusMsg (Just Udp
listen) Cx
cx Message
msg = Udp -> Packet -> SockAddr -> IO ()
O.sendTo Udp
listen (Message -> Packet
O.Packet_Message Message
msg) (AddrInfo -> SockAddr
N.addrAddress AddrInfo
addr)
where addr :: AddrInfo
addr | Bool
isBusMsg Bool -> Bool -> Bool
&& forall a. Maybe a -> Bool
isJust (Cx -> Maybe AddrInfo
cxBusAddr Cx
cx) = forall a. HasCallStack => Maybe a -> a
fromJust forall a b. (a -> b) -> a -> b
$ Cx -> Maybe AddrInfo
cxBusAddr Cx
cx
| Bool
otherwise = Cx -> AddrInfo
cxAddr Cx
cx
sendO Bool
_ Maybe Udp
Nothing Cx
cx Message
msg = forall t. Transport t => t -> Message -> IO ()
O.sendMessage (Cx -> Udp
cxUDP Cx
cx) Message
msg
sendBndl :: Bool -> (Maybe O.Udp) -> Cx -> O.Bundle -> IO ()
sendBndl :: Bool -> Maybe Udp -> Cx -> Bundle -> IO ()
sendBndl Bool
isBusMsg (Just Udp
listen) Cx
cx Bundle
bndl = Udp -> Packet -> SockAddr -> IO ()
O.sendTo Udp
listen (Bundle -> Packet
O.Packet_Bundle Bundle
bndl) (AddrInfo -> SockAddr
N.addrAddress AddrInfo
addr)
where addr :: AddrInfo
addr | Bool
isBusMsg Bool -> Bool -> Bool
&& forall a. Maybe a -> Bool
isJust (Cx -> Maybe AddrInfo
cxBusAddr Cx
cx) = forall a. HasCallStack => Maybe a -> a
fromJust forall a b. (a -> b) -> a -> b
$ Cx -> Maybe AddrInfo
cxBusAddr Cx
cx
| Bool
otherwise = Cx -> AddrInfo
cxAddr Cx
cx
sendBndl Bool
_ Maybe Udp
Nothing Cx
cx Bundle
bndl = forall t. Transport t => t -> Bundle -> IO ()
O.sendBundle (Cx -> Udp
cxUDP Cx
cx) Bundle
bndl
resolve :: String -> String -> IO N.AddrInfo
resolve :: String -> String -> IO AddrInfo
resolve String
host String
port = do let hints :: AddrInfo
hints = AddrInfo
N.defaultHints { addrSocketType :: SocketType
N.addrSocketType = SocketType
N.Stream }
AddrInfo
addr:[AddrInfo]
_ <- Maybe AddrInfo -> Maybe String -> Maybe String -> IO [AddrInfo]
N.getAddrInfo (forall a. a -> Maybe a
Just AddrInfo
hints) (forall a. a -> Maybe a
Just String
host) (forall a. a -> Maybe a
Just String
port)
forall (m :: * -> *) a. Monad m => a -> m a
return AddrInfo
addr
startTidal :: Target -> Config -> IO Stream
startTidal :: Target -> Config -> IO Stream
startTidal Target
target Config
config = Config -> [(Target, [OSC])] -> IO Stream
startStream Config
config [(Target
target, [OSC
superdirtShape])]
startMulti :: [Target] -> Config -> IO ()
startMulti :: [Target] -> Config -> IO ()
startMulti [Target]
_ Config
_ = Handle -> String -> IO ()
hPutStrLn Handle
stderr forall a b. (a -> b) -> a -> b
$ String
"startMulti has been removed, please check the latest documentation on tidalcycles.org"
toDatum :: Value -> O.Datum
toDatum :: Value -> Datum
toDatum (VF Double
x) = forall n. Real n => n -> Datum
O.float Double
x
toDatum (VN Note
x) = forall n. Real n => n -> Datum
O.float Note
x
toDatum (VI Int
x) = forall n. Integral n => n -> Datum
O.int32 Int
x
toDatum (VS String
x) = String -> Datum
O.string String
x
toDatum (VR Rational
x) = forall n. Real n => n -> Datum
O.float forall a b. (a -> b) -> a -> b
$ ((forall a. Fractional a => Rational -> a
fromRational Rational
x) :: Double)
toDatum (VB Bool
True) = forall n. Integral n => n -> Datum
O.int32 (Int
1 :: Int)
toDatum (VB Bool
False) = forall n. Integral n => n -> Datum
O.int32 (Int
0 :: Int)
toDatum (VX [Word8]
xs) = Blob -> Datum
O.Blob forall a b. (a -> b) -> a -> b
$ [Word8] -> Blob
O.blob_pack [Word8]
xs
toDatum Value
_ = forall a. HasCallStack => String -> a
error String
"toDatum: unhandled value"
toData :: OSC -> Event ValueMap -> Maybe [O.Datum]
toData :: OSC -> Event ValueMap -> Maybe [Datum]
toData (OSC {args :: OSC -> Args
args = ArgList [(String, Maybe Value)]
as}) Event ValueMap
e = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Value -> Datum
toDatum)) forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map (\(String
n,Maybe Value
v) -> forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup String
n (forall a b. EventF a b -> b
value Event ValueMap
e) forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Maybe Value
v) [(String, Maybe Value)]
as
toData (OSC {args :: OSC -> Args
args = Named [String]
rqrd}) Event ValueMap
e
| [String] -> Bool
hasRequired [String]
rqrd = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (\(String
n,Value
v) -> [String -> Datum
O.string String
n, Value -> Datum
toDatum Value
v]) forall a b. (a -> b) -> a -> b
$ forall k a. Map k a -> [(k, a)]
Map.toList forall a b. (a -> b) -> a -> b
$ forall a b. EventF a b -> b
value Event ValueMap
e
| Bool
otherwise = forall a. Maybe a
Nothing
where hasRequired :: [String] -> Bool
hasRequired [] = Bool
True
hasRequired [String]
xs = forall (t :: * -> *) a. Foldable t => t a -> Bool
null forall a b. (a -> b) -> a -> b
$ forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [String]
ks)) [String]
xs
ks :: [String]
ks = forall k a. Map k a -> [k]
Map.keys (forall a b. EventF a b -> b
value Event ValueMap
e)
toData OSC
_ Event ValueMap
_ = forall a. Maybe a
Nothing
substitutePath :: String -> ValueMap -> Maybe String
substitutePath :: String -> ValueMap -> Maybe String
substitutePath String
str ValueMap
cm = String -> Maybe String
parse String
str
where parse :: String -> Maybe String
parse [] = forall a. a -> Maybe a
Just []
parse (Char
'{':String
xs) = String -> Maybe String
parseWord String
xs
parse (Char
x:String
xs) = do String
xs' <- String -> Maybe String
parse String
xs
forall (m :: * -> *) a. Monad m => a -> m a
return (Char
xforall a. a -> [a] -> [a]
:String
xs')
parseWord :: String -> Maybe String
parseWord String
xs | String
b forall a. Eq a => a -> a -> Bool
== [] = ValueMap -> String -> Maybe String
getString ValueMap
cm String
a
| Bool
otherwise = do String
v <- ValueMap -> String -> Maybe String
getString ValueMap
cm String
a
String
xs' <- String -> Maybe String
parse (forall a. [a] -> [a]
tail String
b)
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ String
v forall a. [a] -> [a] -> [a]
++ String
xs'
where (String
a,String
b) = forall a. (a -> Bool) -> [a] -> ([a], [a])
break (forall a. Eq a => a -> a -> Bool
== Char
'}') String
xs
getString :: ValueMap -> String -> Maybe String
getString :: ValueMap -> String -> Maybe String
getString ValueMap
cm String
s = (Value -> String
simpleShow forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup String
param ValueMap
cm) forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> String -> Maybe String
defaultValue String
dflt
where (String
param, String
dflt) = forall a. (a -> Bool) -> [a] -> ([a], [a])
break (forall a. Eq a => a -> a -> Bool
== Char
'=') String
s
simpleShow :: Value -> String
simpleShow :: Value -> String
simpleShow (VS String
str) = String
str
simpleShow (VI Int
i) = forall a. Show a => a -> String
show Int
i
simpleShow (VF Double
f) = forall a. Show a => a -> String
show Double
f
simpleShow (VN Note
n) = forall a. Show a => a -> String
show Note
n
simpleShow (VR Rational
r) = forall a. Show a => a -> String
show Rational
r
simpleShow (VB Bool
b) = forall a. Show a => a -> String
show Bool
b
simpleShow (VX [Word8]
xs) = forall a. Show a => a -> String
show [Word8]
xs
simpleShow (VState ValueMap -> (ValueMap, Value)
_) = forall a. Show a => a -> String
show String
"<stateful>"
simpleShow (VPattern Pattern Value
_) = forall a. Show a => a -> String
show String
"<pattern>"
simpleShow (VList [Value]
_) = forall a. Show a => a -> String
show String
"<list>"
defaultValue :: String -> Maybe String
defaultValue :: String -> Maybe String
defaultValue (Char
'=':String
dfltVal) = forall a. a -> Maybe a
Just String
dfltVal
defaultValue String
_ = forall a. Maybe a
Nothing
playStack :: PlayMap -> ControlPattern
playStack :: PlayMap -> ControlPattern
playStack PlayMap
pMap = forall a. [Pattern a] -> Pattern a
stack forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall a b. (a -> b) -> [a] -> [b]
map PlayState -> ControlPattern
pattern) forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall a. (a -> Bool) -> [a] -> [a]
filter PlayState -> Bool
active) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall k a. Map k a -> [a]
Map.elems forall a b. (a -> b) -> a -> b
$ PlayMap
pMap
where active :: PlayState -> Bool
active PlayState
pState = if forall k. Map k PlayState -> Bool
hasSolo PlayMap
pMap
then PlayState -> Bool
solo PlayState
pState
else Bool -> Bool
not (PlayState -> Bool
mute PlayState
pState)
toOSC :: [Int] -> ProcessedEvent -> OSC -> [(Double, Bool, O.Message)]
toOSC :: [Int] -> ProcessedEvent -> OSC -> [(Double, Bool, Message)]
toOSC [Int]
busses ProcessedEvent
pe osc :: OSC
osc@(OSC String
_ Args
_)
= forall a. [Maybe a] -> [a]
catMaybes (Maybe (Double, Bool, Message)
playmsgforall a. a -> [a] -> [a]
:[Maybe (Double, Bool, Message)]
busmsgs)
where
(ValueMap
playmap, ValueMap
busmap) = forall k a. (k -> a -> Bool) -> Map k a -> (Map k a, Map k a)
Map.partitionWithKey (\String
k Value
_ -> forall (t :: * -> *) a. Foldable t => t a -> Bool
null String
k Bool -> Bool -> Bool
|| forall a. [a] -> a
head String
k forall a. Eq a => a -> a -> Bool
/= Char
'^') forall a b. (a -> b) -> a -> b
$ ProcessedEvent -> ValueMap
val ProcessedEvent
pe
playmap' :: ValueMap
playmap' = forall k a. Ord k => Map k a -> Map k a -> Map k a
Map.union (forall k2 k1 a. Ord k2 => (k1 -> k2) -> Map k1 a -> Map k2 a
Map.mapKeys forall a. [a] -> [a]
tail forall a b. (a -> b) -> a -> b
$ forall a b k. (a -> b) -> Map k a -> Map k b
Map.map (\(VI Int
i) -> String -> Value
VS (Char
'c'forall a. a -> [a] -> [a]
:(forall a. Show a => a -> String
show forall a b. (a -> b) -> a -> b
$ Int -> Int
toBus Int
i))) ValueMap
busmap) ValueMap
playmap
val :: ProcessedEvent -> ValueMap
val = forall a b. EventF a b -> b
value forall b c a. (b -> c) -> (a -> b) -> a -> c
. ProcessedEvent -> Event ValueMap
peEvent
playmsg :: Maybe (Double, Bool, Message)
playmsg | ProcessedEvent -> Bool
peHasOnset ProcessedEvent
pe = do
let extra :: ValueMap
extra = forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList [(String
"cps", (Double -> Value
VF (coerce :: forall a b. Coercible a b => a -> b
coerce forall a b. (a -> b) -> a -> b
$! ProcessedEvent -> Beat
peCps ProcessedEvent
pe))),
(String
"delta", Double -> Value
VF (Micros -> Double -> Double
T.addMicrosToOsc (ProcessedEvent -> Micros
peDelta ProcessedEvent
pe) Double
0)),
(String
"cycle", Double -> Value
VF (forall a. Fractional a => Rational -> a
fromRational (ProcessedEvent -> Rational
peCycle ProcessedEvent
pe)))
]
addExtra :: ValueMap
addExtra = forall k a. Ord k => Map k a -> Map k a -> Map k a
Map.union ValueMap
playmap' ValueMap
extra
ts :: Double
ts = (ProcessedEvent -> Double
peOnWholeOrPartOsc ProcessedEvent
pe) forall a. Num a => a -> a -> a
+ Double
nudge
[Datum]
vs <- OSC -> Event ValueMap -> Maybe [Datum]
toData OSC
osc ((ProcessedEvent -> Event ValueMap
peEvent ProcessedEvent
pe) {value :: ValueMap
value = ValueMap
addExtra})
String
mungedPath <- String -> ValueMap -> Maybe String
substitutePath (OSC -> String
path OSC
osc) ValueMap
playmap'
forall (m :: * -> *) a. Monad m => a -> m a
return (Double
ts,
Bool
False,
String -> [Datum] -> Message
O.Message String
mungedPath [Datum]
vs
)
| Bool
otherwise = forall a. Maybe a
Nothing
toBus :: Int -> Int
toBus Int
n | forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Int]
busses = Int
n
| Bool
otherwise = [Int]
busses forall a. [a] -> Int -> a
!!! Int
n
busmsgs :: [Maybe (Double, Bool, Message)]
busmsgs = forall a b. (a -> b) -> [a] -> [b]
map
(\((Char
'^':String
k), (VI Int
b)) -> do Value
v <- forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup String
k ValueMap
playmap
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ (Double
tsPart,
Bool
True,
String -> [Datum] -> Message
O.Message String
"/c_set" [forall n. Integral n => n -> Datum
O.int32 Int
b, Value -> Datum
toDatum Value
v]
)
)
(forall k a. Map k a -> [(k, a)]
Map.toList ValueMap
busmap)
where
tsPart :: Double
tsPart = (ProcessedEvent -> Double
peOnPartOsc ProcessedEvent
pe) forall a. Num a => a -> a -> a
+ Double
nudge
nudge :: Double
nudge = forall a. HasCallStack => Maybe a -> a
fromJust forall a b. (a -> b) -> a -> b
$ Value -> Maybe Double
getF forall a b. (a -> b) -> a -> b
$ forall a. a -> Maybe a -> a
fromMaybe (Double -> Value
VF Double
0) forall a b. (a -> b) -> a -> b
$ forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup String
"nudge" forall a b. (a -> b) -> a -> b
$ ValueMap
playmap
toOSC [Int]
_ ProcessedEvent
pe (OSCContext String
oscpath)
= forall a b. (a -> b) -> [a] -> [b]
map ((Int, Int), (Int, Int)) -> (Double, Bool, Message)
cToM forall a b. (a -> b) -> a -> b
$ Context -> [((Int, Int), (Int, Int))]
contextPosition forall a b. (a -> b) -> a -> b
$ forall a b. EventF a b -> Context
context forall a b. (a -> b) -> a -> b
$ ProcessedEvent -> Event ValueMap
peEvent ProcessedEvent
pe
where cToM :: ((Int,Int),(Int,Int)) -> (Double, Bool, O.Message)
cToM :: ((Int, Int), (Int, Int)) -> (Double, Bool, Message)
cToM ((Int
x, Int
y), (Int
x',Int
y')) = (Double
ts,
Bool
False,
String -> [Datum] -> Message
O.Message String
oscpath forall a b. (a -> b) -> a -> b
$ (String -> Datum
O.string String
ident)forall a. a -> [a] -> [a]
:(forall n. Real n => n -> Datum
O.float (ProcessedEvent -> Micros
peDelta ProcessedEvent
pe))forall a. a -> [a] -> [a]
:(forall n. Real n => n -> Datum
O.float Double
cyc)forall a. a -> [a] -> [a]
:(forall a b. (a -> b) -> [a] -> [b]
map forall n. Integral n => n -> Datum
O.int32 [Int
x,Int
y,Int
x',Int
y'])
)
cyc :: Double
cyc :: Double
cyc = forall a. Fractional a => Rational -> a
fromRational forall a b. (a -> b) -> a -> b
$ ProcessedEvent -> Rational
peCycle ProcessedEvent
pe
nudge :: Double
nudge = forall a. a -> Maybe a -> a
fromMaybe Double
0 forall a b. (a -> b) -> a -> b
$ forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup String
"nudge" (forall a b. EventF a b -> b
value forall a b. (a -> b) -> a -> b
$ ProcessedEvent -> Event ValueMap
peEvent ProcessedEvent
pe) forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Value -> Maybe Double
getF
ident :: String
ident = forall a. a -> Maybe a -> a
fromMaybe String
"unknown" forall a b. (a -> b) -> a -> b
$ forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup String
"_id_" (forall a b. EventF a b -> b
value forall a b. (a -> b) -> a -> b
$ ProcessedEvent -> Event ValueMap
peEvent ProcessedEvent
pe) forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Value -> Maybe String
getS
ts :: Double
ts = (ProcessedEvent -> Double
peOnWholeOrPartOsc ProcessedEvent
pe) forall a. Num a => a -> a -> a
+ Double
nudge
patternTimeID :: String
patternTimeID :: String
patternTimeID = String
"_t_pattern"
updatePattern :: Stream -> ID -> Time -> ControlPattern -> IO ()
updatePattern :: Stream -> ID -> Rational -> ControlPattern -> IO ()
updatePattern Stream
stream ID
k !Rational
t ControlPattern
pat = do
let x :: [Event ValueMap]
x = forall a. Pattern a -> Arc -> [Event a]
queryArc ControlPattern
pat (forall a. a -> a -> ArcF a
Arc Rational
0 Rational
0)
PlayMap
pMap <- seq :: forall a b. a -> b -> b
seq [Event ValueMap]
x forall a b. (a -> b) -> a -> b
$ forall a. MVar a -> IO a
takeMVar (Stream -> MVar PlayMap
sPMapMV Stream
stream)
let playState :: PlayState
playState = Maybe PlayState -> PlayState
updatePS forall a b. (a -> b) -> a -> b
$ forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup (ID -> String
fromID ID
k) PlayMap
pMap
forall a. MVar a -> a -> IO ()
putMVar (Stream -> MVar PlayMap
sPMapMV Stream
stream) forall a b. (a -> b) -> a -> b
$ forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert (ID -> String
fromID ID
k) PlayState
playState PlayMap
pMap
where updatePS :: Maybe PlayState -> PlayState
updatePS (Just PlayState
playState) = do PlayState
playState {pattern :: ControlPattern
pattern = ControlPattern
pat', history :: [ControlPattern]
history = ControlPattern
patforall a. a -> [a] -> [a]
:(PlayState -> [ControlPattern]
history PlayState
playState)}
updatePS Maybe PlayState
Nothing = ControlPattern -> Bool -> Bool -> [ControlPattern] -> PlayState
PlayState ControlPattern
pat' Bool
False Bool
False [ControlPattern
pat']
patControls :: ValueMap
patControls = forall k a. k -> a -> Map k a
Map.singleton String
patternTimeID (Rational -> Value
VR Rational
t)
pat' :: ControlPattern
pat' = forall a. (ValueMap -> ValueMap) -> Pattern a -> Pattern a
withQueryControls (forall k a. Ord k => Map k a -> Map k a -> Map k a
Map.union ValueMap
patControls)
forall a b. (a -> b) -> a -> b
$ ControlPattern
pat forall b. Unionable b => Pattern b -> Pattern b -> Pattern b
# String -> Pattern String -> ControlPattern
pS String
"_id_" (forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ ID -> String
fromID ID
k)
processCps :: T.LinkOperations -> [Event ValueMap] -> IO [ProcessedEvent]
processCps :: LinkOperations -> [Event ValueMap] -> IO [ProcessedEvent]
processCps LinkOperations
ops = forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM Event ValueMap -> IO ProcessedEvent
processEvent
where
processEvent :: Event ValueMap -> IO ProcessedEvent
processEvent :: Event ValueMap -> IO ProcessedEvent
processEvent Event ValueMap
e = do
let wope :: Arc
wope = forall a. Event a -> Arc
wholeOrPart Event ValueMap
e
partStartCycle :: Rational
partStartCycle = forall a. ArcF a -> a
start forall a b. (a -> b) -> a -> b
$ forall a b. EventF a b -> a
part Event ValueMap
e
partStartBeat :: Beat
partStartBeat = (LinkOperations -> Beat -> Beat
T.cyclesToBeat LinkOperations
ops) (forall a b. (Real a, Fractional b) => a -> b
realToFrac Rational
partStartCycle)
onCycle :: Rational
onCycle = forall a. ArcF a -> a
start Arc
wope
onBeat :: Beat
onBeat = (LinkOperations -> Beat -> Beat
T.cyclesToBeat LinkOperations
ops) (forall a b. (Real a, Fractional b) => a -> b
realToFrac Rational
onCycle)
offCycle :: Rational
offCycle = forall a. ArcF a -> a
stop Arc
wope
offBeat :: Beat
offBeat = (LinkOperations -> Beat -> Beat
T.cyclesToBeat LinkOperations
ops) (forall a b. (Real a, Fractional b) => a -> b
realToFrac Rational
offCycle)
Micros
on <- (LinkOperations -> Beat -> IO Micros
T.timeAtBeat LinkOperations
ops) Beat
onBeat
Micros
onPart <- (LinkOperations -> Beat -> IO Micros
T.timeAtBeat LinkOperations
ops) Beat
partStartBeat
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (forall a. Event a -> Bool
eventHasOnset Event ValueMap
e) (do
let cps' :: Maybe Double
cps' = forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup String
"cps" (forall a b. EventF a b -> b
value Event ValueMap
e) forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Value -> Maybe Double
getF
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (forall (m :: * -> *) a. Monad m => a -> m a
return ()) (\Beat
newCps -> (LinkOperations -> Beat -> Micros -> IO ()
T.setTempo LinkOperations
ops) ((LinkOperations -> Beat -> Beat
T.cyclesToBeat LinkOperations
ops) (Beat
newCps forall a. Num a => a -> a -> a
* Beat
60)) Micros
on) forall a b. (a -> b) -> a -> b
$ coerce :: forall a b. Coercible a b => a -> b
coerce Maybe Double
cps'
)
Micros
off <- (LinkOperations -> Beat -> IO Micros
T.timeAtBeat LinkOperations
ops) Beat
offBeat
Beat
bpm <- (LinkOperations -> IO Beat
T.getTempo LinkOperations
ops)
let cps :: Beat
cps = ((LinkOperations -> Beat -> Beat
T.beatToCycles LinkOperations
ops) Beat
bpm) forall a. Fractional a => a -> a -> a
/ Beat
60
let delta :: Micros
delta = Micros
off forall a. Num a => a -> a -> a
- Micros
on
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$! ProcessedEvent {
peHasOnset :: Bool
peHasOnset = forall a. Event a -> Bool
eventHasOnset Event ValueMap
e,
peEvent :: Event ValueMap
peEvent = Event ValueMap
e,
peCps :: Beat
peCps = Beat
cps,
peDelta :: Micros
peDelta = Micros
delta,
peCycle :: Rational
peCycle = Rational
onCycle,
peOnWholeOrPart :: Micros
peOnWholeOrPart = Micros
on,
peOnWholeOrPartOsc :: Double
peOnWholeOrPartOsc = (LinkOperations -> Micros -> Double
T.linkToOscTime LinkOperations
ops) Micros
on,
peOnPart :: Micros
peOnPart = Micros
onPart,
peOnPartOsc :: Double
peOnPartOsc = (LinkOperations -> Micros -> Double
T.linkToOscTime LinkOperations
ops) Micros
onPart
}
streamOnce :: Stream -> ControlPattern -> IO ()
streamOnce :: Stream -> ControlPattern -> IO ()
streamOnce Stream
st ControlPattern
p = do Int
i <- forall (m :: * -> *) a. MonadIO m => (StdGen -> (a, StdGen)) -> m a
getStdRandom forall a b. (a -> b) -> a -> b
$ forall a g. (Random a, RandomGen g) => (a, a) -> g -> (a, g)
randomR (Int
0, Int
8192)
Stream -> ControlPattern -> IO ()
streamFirst Stream
st forall a b. (a -> b) -> a -> b
$ forall a. Rational -> Pattern a -> Pattern a
rotL (forall a. Real a => a -> Rational
toRational (Int
i :: Int)) ControlPattern
p
streamFirst :: Stream -> ControlPattern -> IO ()
streamFirst :: Stream -> ControlPattern -> IO ()
streamFirst Stream
stream ControlPattern
pat = forall a. MVar a -> (a -> IO a) -> IO ()
modifyMVar_ (Stream -> MVar [TempoAction]
sActionsMV Stream
stream) (\[TempoAction]
actions -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ (ControlPattern -> TempoAction
T.SingleTick ControlPattern
pat) forall a. a -> [a] -> [a]
: [TempoAction]
actions)
onTick :: Stream -> TickState -> T.LinkOperations -> ValueMap -> IO ValueMap
onTick :: Stream -> TickState -> LinkOperations -> ValueMap -> IO ValueMap
onTick Stream
stream TickState
st LinkOperations
ops ValueMap
s
= Stream -> TickState -> LinkOperations -> ValueMap -> IO ValueMap
doTick Stream
stream TickState
st LinkOperations
ops ValueMap
s
onSingleTick :: Stream -> T.LinkOperations -> ValueMap -> ControlPattern -> IO ValueMap
onSingleTick :: Stream
-> LinkOperations -> ValueMap -> ControlPattern -> IO ValueMap
onSingleTick Stream
stream LinkOperations
ops ValueMap
s ControlPattern
pat = do
MVar PlayMap
pMapMV <- forall a. a -> IO (MVar a)
newMVar forall a b. (a -> b) -> a -> b
$ forall k a. k -> a -> Map k a
Map.singleton String
"fake"
(PlayState {pattern :: ControlPattern
pattern = ControlPattern
pat,
mute :: Bool
mute = Bool
False,
solo :: Bool
solo = Bool
False,
history :: [ControlPattern]
history = []
}
)
let state :: TickState
state = TickState {tickArc :: Arc
tickArc = (forall a. a -> a -> ArcF a
Arc Rational
0 Rational
1), tickNudge :: Double
tickNudge = Double
0}
Stream -> TickState -> LinkOperations -> ValueMap -> IO ValueMap
doTick (Stream
stream {sPMapMV :: MVar PlayMap
sPMapMV = MVar PlayMap
pMapMV}) TickState
state LinkOperations
ops ValueMap
s
doTick :: Stream -> TickState -> T.LinkOperations -> ValueMap -> IO ValueMap
doTick :: Stream -> TickState -> LinkOperations -> ValueMap -> IO ValueMap
doTick Stream
stream TickState
st LinkOperations
ops ValueMap
sMap =
forall e a. Exception e => (e -> IO a) -> IO a -> IO a
E.handle (\ (SomeException
e :: E.SomeException) -> do
Handle -> String -> IO ()
hPutStrLn Handle
stderr forall a b. (a -> b) -> a -> b
$ String
"Failed to Stream.doTick: " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show SomeException
e
Handle -> String -> IO ()
hPutStrLn Handle
stderr forall a b. (a -> b) -> a -> b
$ String
"Return to previous pattern."
Stream -> IO ()
setPreviousPatternOrSilence Stream
stream
forall (m :: * -> *) a. Monad m => a -> m a
return ValueMap
sMap) (do
PlayMap
pMap <- forall a. MVar a -> IO a
readMVar (Stream -> MVar PlayMap
sPMapMV Stream
stream)
[Int]
busses <- forall a. MVar a -> IO a
readMVar (Stream -> MVar [Int]
sBusses Stream
stream)
ControlPattern -> ControlPattern
sGlobalF <- forall a. MVar a -> IO a
readMVar (Stream -> MVar (ControlPattern -> ControlPattern)
sGlobalFMV Stream
stream)
Beat
bpm <- (LinkOperations -> IO Beat
T.getTempo LinkOperations
ops)
let
cxs :: [Cx]
cxs = Stream -> [Cx]
sCxs Stream
stream
patstack :: ControlPattern
patstack = ControlPattern -> ControlPattern
sGlobalF forall a b. (a -> b) -> a -> b
$ PlayMap -> ControlPattern
playStack PlayMap
pMap
cps :: Beat
cps = ((LinkOperations -> Beat -> Beat
T.beatToCycles LinkOperations
ops) Beat
bpm) forall a. Fractional a => a -> a -> a
/ Beat
60
sMap' :: ValueMap
sMap' = forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert String
"_cps" (Double -> Value
VF forall a b. (a -> b) -> a -> b
$ coerce :: forall a b. Coercible a b => a -> b
coerce Beat
cps) ValueMap
sMap
extraLatency :: Double
extraLatency = TickState -> Double
tickNudge TickState
st
es :: [Event ValueMap]
es = forall b a. Ord b => (a -> b) -> [a] -> [a]
sortOn (forall a. ArcF a -> a
start forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. EventF a b -> a
part) forall a b. (a -> b) -> a -> b
$ forall a. Pattern a -> State -> [Event a]
query ControlPattern
patstack (State {arc :: Arc
arc = TickState -> Arc
tickArc TickState
st,
controls :: ValueMap
controls = ValueMap
sMap'
}
)
(ValueMap
sMap'', [Event ValueMap]
es') = ValueMap -> [Event ValueMap] -> (ValueMap, [Event ValueMap])
resolveState ValueMap
sMap' [Event ValueMap]
es
[ProcessedEvent]
tes <- LinkOperations -> [Event ValueMap] -> IO [ProcessedEvent]
processCps LinkOperations
ops [Event ValueMap]
es'
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [Cx]
cxs forall a b. (a -> b) -> a -> b
$ \cx :: Cx
cx@(Cx Target
target Udp
_ [OSC]
oscs AddrInfo
_ Maybe AddrInfo
_) -> do
let latency :: Double
latency = Target -> Double
oLatency Target
target
ms :: [(Double, Bool, Message)]
ms = forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (\ProcessedEvent
e -> forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap ([Int] -> ProcessedEvent -> OSC -> [(Double, Bool, Message)]
toOSC [Int]
busses ProcessedEvent
e) [OSC]
oscs) [ProcessedEvent]
tes
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [(Double, Bool, Message)]
ms forall a b. (a -> b) -> a -> b
$ \ (Double, Bool, Message)
m -> (do
Maybe Udp
-> Cx -> Double -> Double -> (Double, Bool, Message) -> IO ()
send (Stream -> Maybe Udp
sListen Stream
stream) Cx
cx Double
latency Double
extraLatency (Double, Bool, Message)
m) forall e a. Exception e => IO a -> (e -> IO a) -> IO a
`E.catch` \ (SomeException
e :: E.SomeException) -> do
Handle -> String -> IO ()
hPutStrLn Handle
stderr forall a b. (a -> b) -> a -> b
$ String
"Failed to send. Is the '" forall a. [a] -> [a] -> [a]
++ Target -> String
oName Target
target forall a. [a] -> [a] -> [a]
++ String
"' target running? " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show SomeException
e
ValueMap
sMap'' seq :: forall a b. a -> b -> b
`seq` forall (m :: * -> *) a. Monad m => a -> m a
return ValueMap
sMap'')
setPreviousPatternOrSilence :: Stream -> IO ()
setPreviousPatternOrSilence :: Stream -> IO ()
setPreviousPatternOrSilence Stream
stream =
forall a. MVar a -> (a -> IO a) -> IO ()
modifyMVar_ (Stream -> MVar PlayMap
sPMapMV Stream
stream) forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. Monad m => a -> m a
return
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b k. (a -> b) -> Map k a -> Map k b
Map.map ( \ PlayState
pMap -> case PlayState -> [ControlPattern]
history PlayState
pMap of
ControlPattern
_:ControlPattern
p:[ControlPattern]
ps -> PlayState
pMap { pattern :: ControlPattern
pattern = ControlPattern
p, history :: [ControlPattern]
history = ControlPattern
pforall a. a -> [a] -> [a]
:[ControlPattern]
ps }
[ControlPattern]
_ -> PlayState
pMap { pattern :: ControlPattern
pattern = forall a. Pattern a
silence, history :: [ControlPattern]
history = [forall a. Pattern a
silence] }
)
send :: Maybe O.Udp -> Cx -> Double -> Double -> (Double, Bool, O.Message) -> IO ()
send :: Maybe Udp
-> Cx -> Double -> Double -> (Double, Bool, Message) -> IO ()
send Maybe Udp
listen Cx
cx Double
latency Double
extraLatency (Double
time, Bool
isBusMsg, Message
m)
| Target -> Schedule
oSchedule Target
target forall a. Eq a => a -> a -> Bool
== StampStyle -> Schedule
Pre StampStyle
BundleStamp = Bool -> Maybe Udp -> Cx -> Bundle -> IO ()
sendBndl Bool
isBusMsg Maybe Udp
listen Cx
cx forall a b. (a -> b) -> a -> b
$ Double -> [Message] -> Bundle
O.Bundle Double
timeWithLatency [Message
m]
| Target -> Schedule
oSchedule Target
target forall a. Eq a => a -> a -> Bool
== StampStyle -> Schedule
Pre StampStyle
MessageStamp = Bool -> Maybe Udp -> Cx -> Message -> IO ()
sendO Bool
isBusMsg Maybe Udp
listen Cx
cx forall a b. (a -> b) -> a -> b
$ Message -> Message
addtime Message
m
| Bool
otherwise = do ThreadId
_ <- IO () -> IO ThreadId
forkOS forall a b. (a -> b) -> a -> b
$ do Double
now <- forall (m :: * -> *). MonadIO m => m Double
O.time
Int -> IO ()
threadDelay forall a b. (a -> b) -> a -> b
$ forall a b. (RealFrac a, Integral b) => a -> b
floor forall a b. (a -> b) -> a -> b
$ (Double
timeWithLatency forall a. Num a => a -> a -> a
- Double
now) forall a. Num a => a -> a -> a
* Double
1000000
Bool -> Maybe Udp -> Cx -> Message -> IO ()
sendO Bool
isBusMsg Maybe Udp
listen Cx
cx Message
m
forall (m :: * -> *) a. Monad m => a -> m a
return ()
where addtime :: Message -> Message
addtime (O.Message String
mpath [Datum]
params) = String -> [Datum] -> Message
O.Message String
mpath ((forall n. Integral n => n -> Datum
O.int32 Int
sec)forall a. a -> [a] -> [a]
:((forall n. Integral n => n -> Datum
O.int32 Int
usec)forall a. a -> [a] -> [a]
:[Datum]
params))
ut :: Double
ut = forall n. Num n => n -> n
O.ntpr_to_posix Double
timeWithLatency
sec :: Int
sec :: Int
sec = forall a b. (RealFrac a, Integral b) => a -> b
floor Double
ut
usec :: Int
usec :: Int
usec = forall a b. (RealFrac a, Integral b) => a -> b
floor forall a b. (a -> b) -> a -> b
$ Double
1000000 forall a. Num a => a -> a -> a
* (Double
ut forall a. Num a => a -> a -> a
- (forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
sec))
target :: Target
target = Cx -> Target
cxTarget Cx
cx
timeWithLatency :: Double
timeWithLatency = Double
time forall a. Num a => a -> a -> a
- Double
latency forall a. Num a => a -> a -> a
+ Double
extraLatency
streamNudgeAll :: Stream -> Double -> IO ()
streamNudgeAll :: Stream -> Double -> IO ()
streamNudgeAll Stream
s Double
nudge = MVar [TempoAction] -> Double -> IO ()
T.setNudge (Stream -> MVar [TempoAction]
sActionsMV Stream
s) Double
nudge
streamResetCycles :: Stream -> IO ()
streamResetCycles :: Stream -> IO ()
streamResetCycles Stream
s = Stream -> Rational -> IO ()
streamSetCycle Stream
s Rational
0
streamSetCycle :: Stream -> Time -> IO ()
streamSetCycle :: Stream -> Rational -> IO ()
streamSetCycle Stream
s Rational
cyc = Rational -> MVar [TempoAction] -> IO ()
T.setCycle Rational
cyc (Stream -> MVar [TempoAction]
sActionsMV Stream
s)
hasSolo :: Map.Map k PlayState -> Bool
hasSolo :: forall k. Map k PlayState -> Bool
hasSolo = (forall a. Ord a => a -> a -> Bool
>= Int
1) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (t :: * -> *) a. Foldable t => t a -> Int
length forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. (a -> Bool) -> [a] -> [a]
filter PlayState -> Bool
solo forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall k a. Map k a -> [a]
Map.elems
streamList :: Stream -> IO ()
streamList :: Stream -> IO ()
streamList Stream
s = do PlayMap
pMap <- forall a. MVar a -> IO a
readMVar (Stream -> MVar PlayMap
sPMapMV Stream
s)
let hs :: Bool
hs = forall k. Map k PlayState -> Bool
hasSolo PlayMap
pMap
String -> IO ()
putStrLn forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (Bool -> (String, PlayState) -> String
showKV Bool
hs) forall a b. (a -> b) -> a -> b
$ forall k a. Map k a -> [(k, a)]
Map.toList PlayMap
pMap
where showKV :: Bool -> (PatId, PlayState) -> String
showKV :: Bool -> (String, PlayState) -> String
showKV Bool
True (String
k, (PlayState {solo :: PlayState -> Bool
solo = Bool
True})) = String
k forall a. [a] -> [a] -> [a]
++ String
" - solo\n"
showKV Bool
True (String
k, PlayState
_) = String
"(" forall a. [a] -> [a] -> [a]
++ String
k forall a. [a] -> [a] -> [a]
++ String
")\n"
showKV Bool
False (String
k, (PlayState {solo :: PlayState -> Bool
solo = Bool
False})) = String
k forall a. [a] -> [a] -> [a]
++ String
"\n"
showKV Bool
False (String
k, PlayState
_) = String
"(" forall a. [a] -> [a] -> [a]
++ String
k forall a. [a] -> [a] -> [a]
++ String
") - muted\n"
streamReplace :: Stream -> ID -> ControlPattern -> IO ()
streamReplace :: Stream -> ID -> ControlPattern -> IO ()
streamReplace Stream
s ID
k !ControlPattern
pat
= forall a. MVar a -> (a -> IO a) -> IO ()
modifyMVar_ (Stream -> MVar [TempoAction]
sActionsMV Stream
s) (\[TempoAction]
actions -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ (ID -> ControlPattern -> TempoAction
T.StreamReplace ID
k ControlPattern
pat) forall a. a -> [a] -> [a]
: [TempoAction]
actions)
streamMute :: Stream -> ID -> IO ()
streamMute :: Stream -> ID -> IO ()
streamMute Stream
s ID
k = Stream -> [ID] -> (PlayState -> PlayState) -> IO ()
withPatIds Stream
s [ID
k] (\PlayState
x -> PlayState
x {mute :: Bool
mute = Bool
True})
streamMutes :: Stream -> [ID] -> IO ()
streamMutes :: Stream -> [ID] -> IO ()
streamMutes Stream
s [ID]
ks = Stream -> [ID] -> (PlayState -> PlayState) -> IO ()
withPatIds Stream
s [ID]
ks (\PlayState
x -> PlayState
x {mute :: Bool
mute = Bool
True})
streamUnmute :: Stream -> ID -> IO ()
streamUnmute :: Stream -> ID -> IO ()
streamUnmute Stream
s ID
k = Stream -> [ID] -> (PlayState -> PlayState) -> IO ()
withPatIds Stream
s [ID
k] (\PlayState
x -> PlayState
x {mute :: Bool
mute = Bool
False})
streamSolo :: Stream -> ID -> IO ()
streamSolo :: Stream -> ID -> IO ()
streamSolo Stream
s ID
k = Stream -> [ID] -> (PlayState -> PlayState) -> IO ()
withPatIds Stream
s [ID
k] (\PlayState
x -> PlayState
x {solo :: Bool
solo = Bool
True})
streamUnsolo :: Stream -> ID -> IO ()
streamUnsolo :: Stream -> ID -> IO ()
streamUnsolo Stream
s ID
k = Stream -> [ID] -> (PlayState -> PlayState) -> IO ()
withPatIds Stream
s [ID
k] (\PlayState
x -> PlayState
x {solo :: Bool
solo = Bool
False})
withPatIds :: Stream -> [ID] -> (PlayState -> PlayState) -> IO ()
withPatIds :: Stream -> [ID] -> (PlayState -> PlayState) -> IO ()
withPatIds Stream
s [ID]
ks PlayState -> PlayState
f
= do PlayMap
playMap <- forall a. MVar a -> IO a
takeMVar forall a b. (a -> b) -> a -> b
$ Stream -> MVar PlayMap
sPMapMV Stream
s
let pMap' :: PlayMap
pMap' = forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (forall k a. Ord k => (a -> Maybe a) -> k -> Map k a -> Map k a
Map.update (\PlayState
x -> forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ PlayState -> PlayState
f PlayState
x)) PlayMap
playMap (forall a b. (a -> b) -> [a] -> [b]
map ID -> String
fromID [ID]
ks)
forall a. MVar a -> a -> IO ()
putMVar (Stream -> MVar PlayMap
sPMapMV Stream
s) PlayMap
pMap'
forall (m :: * -> *) a. Monad m => a -> m a
return ()
streamMuteAll :: Stream -> IO ()
streamMuteAll :: Stream -> IO ()
streamMuteAll Stream
s = forall a. MVar a -> (a -> IO a) -> IO ()
modifyMVar_ (Stream -> MVar PlayMap
sPMapMV Stream
s) forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. Monad m => a -> m a
return forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\PlayState
x -> PlayState
x {mute :: Bool
mute = Bool
True})
streamHush :: Stream -> IO ()
streamHush :: Stream -> IO ()
streamHush Stream
s = forall a. MVar a -> (a -> IO a) -> IO ()
modifyMVar_ (Stream -> MVar PlayMap
sPMapMV Stream
s) forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. Monad m => a -> m a
return forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\PlayState
x -> PlayState
x {pattern :: ControlPattern
pattern = forall a. Pattern a
silence, history :: [ControlPattern]
history = forall a. Pattern a
silenceforall a. a -> [a] -> [a]
:PlayState -> [ControlPattern]
history PlayState
x})
streamUnmuteAll :: Stream -> IO ()
streamUnmuteAll :: Stream -> IO ()
streamUnmuteAll Stream
s = forall a. MVar a -> (a -> IO a) -> IO ()
modifyMVar_ (Stream -> MVar PlayMap
sPMapMV Stream
s) forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. Monad m => a -> m a
return forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\PlayState
x -> PlayState
x {mute :: Bool
mute = Bool
False})
streamUnsoloAll :: Stream -> IO ()
streamUnsoloAll :: Stream -> IO ()
streamUnsoloAll Stream
s = forall a. MVar a -> (a -> IO a) -> IO ()
modifyMVar_ (Stream -> MVar PlayMap
sPMapMV Stream
s) forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. Monad m => a -> m a
return forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\PlayState
x -> PlayState
x {solo :: Bool
solo = Bool
False})
streamSilence :: Stream -> ID -> IO ()
streamSilence :: Stream -> ID -> IO ()
streamSilence Stream
s ID
k = Stream -> [ID] -> (PlayState -> PlayState) -> IO ()
withPatIds Stream
s [ID
k] (\PlayState
x -> PlayState
x {pattern :: ControlPattern
pattern = forall a. Pattern a
silence, history :: [ControlPattern]
history = forall a. Pattern a
silenceforall a. a -> [a] -> [a]
:PlayState -> [ControlPattern]
history PlayState
x})
streamAll :: Stream -> (ControlPattern -> ControlPattern) -> IO ()
streamAll :: Stream -> (ControlPattern -> ControlPattern) -> IO ()
streamAll Stream
s ControlPattern -> ControlPattern
f = do ControlPattern -> ControlPattern
_ <- forall a. MVar a -> a -> IO a
swapMVar (Stream -> MVar (ControlPattern -> ControlPattern)
sGlobalFMV Stream
s) ControlPattern -> ControlPattern
f
forall (m :: * -> *) a. Monad m => a -> m a
return ()
streamGet :: Stream -> String -> IO (Maybe Value)
streamGet :: Stream -> String -> IO (Maybe Value)
streamGet Stream
s String
k = forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup String
k forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. MVar a -> IO a
readMVar (Stream -> MVar ValueMap
sStateMV Stream
s)
streamSet :: Valuable a => Stream -> String -> Pattern a -> IO ()
streamSet :: forall a. Valuable a => Stream -> String -> Pattern a -> IO ()
streamSet Stream
s String
k Pattern a
pat = do ValueMap
sMap <- forall a. MVar a -> IO a
takeMVar forall a b. (a -> b) -> a -> b
$ Stream -> MVar ValueMap
sStateMV Stream
s
let pat' :: Pattern Value
pat' = forall a. Valuable a => a -> Value
toValue forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Pattern a
pat
sMap' :: ValueMap
sMap' = forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert String
k (Pattern Value -> Value
VPattern Pattern Value
pat') ValueMap
sMap
forall a. MVar a -> a -> IO ()
putMVar (Stream -> MVar ValueMap
sStateMV Stream
s) forall a b. (a -> b) -> a -> b
$ ValueMap
sMap'
streamSetI :: Stream -> String -> Pattern Int -> IO ()
streamSetI :: Stream -> String -> Pattern Int -> IO ()
streamSetI = forall a. Valuable a => Stream -> String -> Pattern a -> IO ()
streamSet
streamSetF :: Stream -> String -> Pattern Double -> IO ()
streamSetF :: Stream -> String -> Pattern Double -> IO ()
streamSetF = forall a. Valuable a => Stream -> String -> Pattern a -> IO ()
streamSet
streamSetS :: Stream -> String -> Pattern String -> IO ()
streamSetS :: Stream -> String -> Pattern String -> IO ()
streamSetS = forall a. Valuable a => Stream -> String -> Pattern a -> IO ()
streamSet
streamSetB :: Stream -> String -> Pattern Bool -> IO ()
streamSetB :: Stream -> String -> Pattern Bool -> IO ()
streamSetB = forall a. Valuable a => Stream -> String -> Pattern a -> IO ()
streamSet
streamSetR :: Stream -> String -> Pattern Rational -> IO ()
streamSetR :: Stream -> String -> Pattern Rational -> IO ()
streamSetR = forall a. Valuable a => Stream -> String -> Pattern a -> IO ()
streamSet
openListener :: Config -> IO (Maybe O.Udp)
openListener :: Config -> IO (Maybe Udp)
openListener Config
c
| Config -> Bool
cCtrlListen Config
c = forall a. IO a -> (SomeException -> IO a) -> IO a
catchAny IO (Maybe Udp)
run (\SomeException
_ -> do Config -> String -> IO ()
verbose Config
c String
"That port isn't available, perhaps another Tidal instance is already listening on that port?"
forall (m :: * -> *) a. Monad m => a -> m a
return forall a. Maybe a
Nothing
)
| Bool
otherwise = forall (m :: * -> *) a. Monad m => a -> m a
return forall a. Maybe a
Nothing
where
run :: IO (Maybe Udp)
run = do Udp
sock <- String -> Int -> IO Udp
O.udpServer (Config -> String
cCtrlAddr Config
c) (Config -> Int
cCtrlPort Config
c)
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Config -> Bool
cCtrlBroadcast Config
c) forall a b. (a -> b) -> a -> b
$ Socket -> SocketOption -> Int -> IO ()
N.setSocketOption (Udp -> Socket
O.udpSocket Udp
sock) SocketOption
N.Broadcast Int
1
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a. a -> Maybe a
Just Udp
sock
catchAny :: IO a -> (E.SomeException -> IO a) -> IO a
catchAny :: forall a. IO a -> (SomeException -> IO a) -> IO a
catchAny = forall e a. Exception e => IO a -> (e -> IO a) -> IO a
E.catch
ctrlResponder :: Int -> Config -> Stream -> IO ()
ctrlResponder :: Int -> Config -> Stream -> IO ()
ctrlResponder Int
waits Config
c (stream :: Stream
stream@(Stream {sListen :: Stream -> Maybe Udp
sListen = Just Udp
sock}))
= do [Message]
ms <- forall t. Transport t => Double -> t -> IO [Message]
recvMessagesTimeout Double
2 Udp
sock
if (forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Message]
ms)
then do IO ()
checkHandshake
Int -> Config -> Stream -> IO ()
ctrlResponder (Int
waitsforall a. Num a => a -> a -> a
+Int
1) Config
c Stream
stream
else do forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ Message -> IO ()
act [Message]
ms
Int -> Config -> Stream -> IO ()
ctrlResponder Int
0 Config
c Stream
stream
where
checkHandshake :: IO ()
checkHandshake = do [Int]
busses <- forall a. MVar a -> IO a
readMVar (Stream -> MVar [Int]
sBusses Stream
stream)
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Int]
busses) forall a b. (a -> b) -> a -> b
$ do forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Int
waits forall a. Eq a => a -> a -> Bool
== Int
0) forall a b. (a -> b) -> a -> b
$ Config -> String -> IO ()
verbose Config
c forall a b. (a -> b) -> a -> b
$ String
"Waiting for SuperDirt (v.1.7.2 or higher).."
Stream -> IO ()
sendHandshakes Stream
stream
act :: Message -> IO ()
act (O.Message String
"/dirt/hello" [Datum]
_) = Stream -> IO ()
sendHandshakes Stream
stream
act (O.Message String
"/dirt/handshake/reply" [Datum]
xs) = do [Int]
prev <- forall a. MVar a -> a -> IO a
swapMVar (Stream -> MVar [Int]
sBusses Stream
stream) forall a b. (a -> b) -> a -> b
$ forall {a}. Integral a => [Datum] -> [a]
bufferIndices [Datum]
xs
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Int]
prev) forall a b. (a -> b) -> a -> b
$ Config -> String -> IO ()
verbose Config
c forall a b. (a -> b) -> a -> b
$ String
"Connected to SuperDirt."
forall (m :: * -> *) a. Monad m => a -> m a
return ()
where
bufferIndices :: [Datum] -> [a]
bufferIndices [] = []
bufferIndices (Datum
x:[Datum]
xs') | Datum
x forall a. Eq a => a -> a -> Bool
== (Ascii -> Datum
O.AsciiString forall a b. (a -> b) -> a -> b
$ String -> Ascii
O.ascii String
"&controlBusIndices") = forall a. [Maybe a] -> [a]
catMaybes forall a b. (a -> b) -> a -> b
$ forall a. (a -> Bool) -> [a] -> [a]
takeWhile forall a. Maybe a -> Bool
isJust forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map forall i. Integral i => Datum -> Maybe i
O.datum_integral [Datum]
xs'
| Bool
otherwise = [Datum] -> [a]
bufferIndices [Datum]
xs'
act (O.Message String
"/ctrl" (O.Int32 Int32
k:Datum
v:[]))
= Message -> IO ()
act (String -> [Datum] -> Message
O.Message String
"/ctrl" [String -> Datum
O.string forall a b. (a -> b) -> a -> b
$ forall a. Show a => a -> String
show Int32
k,Datum
v])
act (O.Message String
"/ctrl" (O.AsciiString Ascii
k:v :: Datum
v@(O.Float Float
_):[]))
= String -> Value -> IO ()
add (Ascii -> String
O.ascii_to_string Ascii
k) (Double -> Value
VF (forall a. HasCallStack => Maybe a -> a
fromJust forall a b. (a -> b) -> a -> b
$ forall n. Floating n => Datum -> Maybe n
O.datum_floating Datum
v))
act (O.Message String
"/ctrl" (O.AsciiString Ascii
k:O.AsciiString Ascii
v:[]))
= String -> Value -> IO ()
add (Ascii -> String
O.ascii_to_string Ascii
k) (String -> Value
VS (Ascii -> String
O.ascii_to_string Ascii
v))
act (O.Message String
"/ctrl" (O.AsciiString Ascii
k:O.Int32 Int32
v:[]))
= String -> Value -> IO ()
add (Ascii -> String
O.ascii_to_string Ascii
k) (Int -> Value
VI (forall a b. (Integral a, Num b) => a -> b
fromIntegral Int32
v))
act (O.Message String
"/mute" (Datum
k:[]))
= Datum -> (ID -> IO ()) -> IO ()
withID Datum
k forall a b. (a -> b) -> a -> b
$ Stream -> ID -> IO ()
streamMute Stream
stream
act (O.Message String
"/unmute" (Datum
k:[]))
= Datum -> (ID -> IO ()) -> IO ()
withID Datum
k forall a b. (a -> b) -> a -> b
$ Stream -> ID -> IO ()
streamUnmute Stream
stream
act (O.Message String
"/solo" (Datum
k:[]))
= Datum -> (ID -> IO ()) -> IO ()
withID Datum
k forall a b. (a -> b) -> a -> b
$ Stream -> ID -> IO ()
streamSolo Stream
stream
act (O.Message String
"/unsolo" (Datum
k:[]))
= Datum -> (ID -> IO ()) -> IO ()
withID Datum
k forall a b. (a -> b) -> a -> b
$ Stream -> ID -> IO ()
streamUnsolo Stream
stream
act (O.Message String
"/muteAll" [])
= Stream -> IO ()
streamMuteAll Stream
stream
act (O.Message String
"/unmuteAll" [])
= Stream -> IO ()
streamUnmuteAll Stream
stream
act (O.Message String
"/unsoloAll" [])
= Stream -> IO ()
streamUnsoloAll Stream
stream
act (O.Message String
"/hush" [])
= Stream -> IO ()
streamHush Stream
stream
act (O.Message String
"/silence" (Datum
k:[]))
= Datum -> (ID -> IO ()) -> IO ()
withID Datum
k forall a b. (a -> b) -> a -> b
$ Stream -> ID -> IO ()
streamSilence Stream
stream
act Message
m = Handle -> String -> IO ()
hPutStrLn Handle
stderr forall a b. (a -> b) -> a -> b
$ String
"Unhandled OSC: " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show Message
m
add :: String -> Value -> IO ()
add :: String -> Value -> IO ()
add String
k Value
v = do ValueMap
sMap <- forall a. MVar a -> IO a
takeMVar (Stream -> MVar ValueMap
sStateMV Stream
stream)
forall a. MVar a -> a -> IO ()
putMVar (Stream -> MVar ValueMap
sStateMV Stream
stream) forall a b. (a -> b) -> a -> b
$ forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert String
k Value
v ValueMap
sMap
forall (m :: * -> *) a. Monad m => a -> m a
return ()
withID :: O.Datum -> (ID -> IO ()) -> IO ()
withID :: Datum -> (ID -> IO ()) -> IO ()
withID (O.AsciiString Ascii
k) ID -> IO ()
func = ID -> IO ()
func forall a b. (a -> b) -> a -> b
$ (String -> ID
ID forall b c a. (b -> c) -> (a -> b) -> a -> c
. Ascii -> String
O.ascii_to_string) Ascii
k
withID (O.Int32 Int32
k) ID -> IO ()
func = ID -> IO ()
func forall a b. (a -> b) -> a -> b
$ (String -> ID
ID forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Show a => a -> String
show) Int32
k
withID Datum
_ ID -> IO ()
_ = forall (m :: * -> *) a. Monad m => a -> m a
return ()
ctrlResponder Int
_ Config
_ Stream
_ = forall (m :: * -> *) a. Monad m => a -> m a
return ()
verbose :: Config -> String -> IO ()
verbose :: Config -> String -> IO ()
verbose Config
c String
s = forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Config -> Bool
cVerbose Config
c) forall a b. (a -> b) -> a -> b
$ String -> IO ()
putStrLn String
s
recvMessagesTimeout :: (O.Transport t) => Double -> t -> IO [O.Message]
recvMessagesTimeout :: forall t. Transport t => Double -> t -> IO [Message]
recvMessagesTimeout Double
n t
sock = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] Packet -> [Message]
O.packetMessages) forall a b. (a -> b) -> a -> b
$ forall t. Transport t => Double -> t -> IO (Maybe Packet)
O.recvPacketTimeout Double
n t
sock
streamGetcps :: Stream -> IO Double
streamGetcps :: Stream -> IO Double
streamGetcps Stream
s = do
let config :: Config
config = Stream -> Config
sConfig Stream
s
SessionState
ss <- AbletonLink -> IO SessionState
Link.createAndCaptureAppSessionState (Stream -> AbletonLink
sLink Stream
s)
Beat
bpm <- SessionState -> IO Beat
Link.getTempo SessionState
ss
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$! coerce :: forall a b. Coercible a b => a -> b
coerce forall a b. (a -> b) -> a -> b
$ Beat
bpm forall a. Fractional a => a -> a -> a
/ (Config -> Beat
cBeatsPerCycle Config
config) forall a. Fractional a => a -> a -> a
/ Beat
60
streamGetnow :: Stream -> IO Double
streamGetnow :: Stream -> IO Double
streamGetnow Stream
s = do
let config :: Config
config = Stream -> Config
sConfig Stream
s
SessionState
ss <- AbletonLink -> IO SessionState
Link.createAndCaptureAppSessionState (Stream -> AbletonLink
sLink Stream
s)
Micros
now <- AbletonLink -> IO Micros
Link.clock (Stream -> AbletonLink
sLink Stream
s)
Beat
beat <- SessionState -> Micros -> Beat -> IO Beat
Link.beatAtTime SessionState
ss Micros
now (Config -> Beat
cQuantum Config
config)
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$! coerce :: forall a b. Coercible a b => a -> b
coerce forall a b. (a -> b) -> a -> b
$ Beat
beat forall a. Fractional a => a -> a -> a
/ (Config -> Beat
cBeatsPerCycle Config
config)