{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# OPTIONS_GHC -fno-warn-missing-fields #-}
module Sound.Tidal.Stream.Process where
import Control.Applicative ((<|>))
import Control.Concurrent.MVar
( MVar,
modifyMVar_,
newMVar,
putMVar,
readMVar,
takeMVar,
)
import qualified Control.Exception as E
import Control.Monad (forM_, when)
import Data.Coerce (coerce)
import Data.List (sortOn)
import qualified Data.Map.Strict as Map
import Data.Maybe (catMaybes, fromJust, fromMaybe)
import qualified Sound.Osc.Fd as O
import qualified Sound.Tidal.Clock as Clock
import Sound.Tidal.Core (stack, (#))
import Sound.Tidal.ID (ID (fromID))
import qualified Sound.Tidal.Link as Link
import Sound.Tidal.Params (pS)
import Sound.Tidal.Pattern
import Sound.Tidal.Pattern.Types (patternTimeID)
import Sound.Tidal.Show ()
import Sound.Tidal.Stream.Target (send)
import Sound.Tidal.Stream.Types
import Sound.Tidal.Utils ((!!!))
import System.IO (hPutStrLn, stderr)
data ProcessedEvent = ProcessedEvent
{ ProcessedEvent -> Bool
peHasOnset :: Bool,
ProcessedEvent -> Event ValueMap
peEvent :: Event ValueMap,
ProcessedEvent -> Double
peCps :: Double,
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
}
doTick ::
MVar ValueMap ->
MVar PlayMap ->
MVar (ControlPattern -> ControlPattern) ->
[Cx] ->
(Time, Time) ->
Double ->
Clock.ClockConfig ->
Clock.ClockRef ->
(Link.SessionState, Link.SessionState) ->
IO ()
doTick :: MVar ValueMap
-> MVar PlayMap
-> MVar (ControlPattern -> ControlPattern)
-> [Cx]
-> (Rational, Rational)
-> Double
-> ClockConfig
-> ClockRef
-> (SessionState, SessionState)
-> IO ()
doTick MVar ValueMap
stateMV MVar PlayMap
playMV MVar (ControlPattern -> ControlPattern)
globalFMV [Cx]
cxs (Rational
st, Rational
end) Double
nudge ClockConfig
cconf ClockRef
cref (SessionState
ss, SessionState
temposs) =
(SomeException -> IO ()) -> IO () -> IO ()
forall e a. Exception e => (e -> IO a) -> IO a -> IO a
E.handle SomeException -> IO ()
handleException (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
MVar ValueMap -> (ValueMap -> IO ValueMap) -> IO ()
forall a. MVar a -> (a -> IO a) -> IO ()
modifyMVar_ MVar ValueMap
stateMV ((ValueMap -> IO ValueMap) -> IO ())
-> (ValueMap -> IO ValueMap) -> IO ()
forall a b. (a -> b) -> a -> b
$ \ValueMap
sMap -> do
PlayMap
pMap <- MVar PlayMap -> IO PlayMap
forall a. MVar a -> IO a
readMVar MVar PlayMap
playMV
ControlPattern -> ControlPattern
sGlobalF <- MVar (ControlPattern -> ControlPattern)
-> IO (ControlPattern -> ControlPattern)
forall a. MVar a -> IO a
readMVar MVar (ControlPattern -> ControlPattern)
globalFMV
Rational
bpm <- SessionState -> IO Rational
Clock.getTempo SessionState
ss
let cps :: Double
cps = ClockConfig -> Double -> Double
Clock.beatToCycles ClockConfig
cconf (Rational -> Double
forall a. Fractional a => Rational -> a
fromRational Rational
bpm) Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
60
cycleLatency :: Rational
cycleLatency = Double -> Rational
forall a. Real a => a -> Rational
toRational (Double -> Rational) -> Double -> Rational
forall a b. (a -> b) -> a -> b
$ Double
nudge Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
cps
patstack :: ControlPattern
patstack = Rational -> ControlPattern -> ControlPattern
forall a. Rational -> Pattern a -> Pattern a
rotR Rational
cycleLatency (ControlPattern -> ControlPattern)
-> ControlPattern -> ControlPattern
forall a b. (a -> b) -> a -> b
$ ControlPattern -> ControlPattern
sGlobalF (ControlPattern -> ControlPattern)
-> ControlPattern -> ControlPattern
forall a b. (a -> b) -> a -> b
$ PlayMap -> ControlPattern
playStack PlayMap
pMap
sMap' :: ValueMap
sMap' = PatId -> Value -> ValueMap -> ValueMap
forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert PatId
"_cps" (Double -> Value
VF (Double -> Value) -> Double -> Value
forall a b. (a -> b) -> a -> b
$ Double -> Double
forall a b. Coercible a b => a -> b
coerce Double
cps) ValueMap
sMap
es :: [Event ValueMap]
es =
(Event ValueMap -> Rational)
-> [Event ValueMap] -> [Event ValueMap]
forall b a. Ord b => (a -> b) -> [a] -> [a]
sortOn (ArcF Rational -> Rational
forall a. ArcF a -> a
start (ArcF Rational -> Rational)
-> (Event ValueMap -> ArcF Rational) -> Event ValueMap -> Rational
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Event ValueMap -> ArcF Rational
forall a b. EventF a b -> a
part) ([Event ValueMap] -> [Event ValueMap])
-> [Event ValueMap] -> [Event ValueMap]
forall a b. (a -> b) -> a -> b
$
ControlPattern -> State -> [Event ValueMap]
forall a. Pattern a -> State -> [Event a]
query
ControlPattern
patstack
( State
{ arc :: ArcF Rational
arc = Rational -> Rational -> ArcF Rational
forall a. a -> a -> ArcF a
Arc Rational
st Rational
end,
controls :: ValueMap
controls = ValueMap
sMap'
}
)
(ValueMap
sMap'', [Event ValueMap]
es') = ValueMap -> [Event ValueMap] -> (ValueMap, [Event ValueMap])
resolveState ValueMap
sMap' [Event ValueMap]
es
[ProcessedEvent]
tes <- ClockConfig
-> ClockRef
-> (SessionState, SessionState)
-> [Event ValueMap]
-> IO [ProcessedEvent]
processCps ClockConfig
cconf ClockRef
cref (SessionState
ss, SessionState
temposs) [Event ValueMap]
es'
[Cx] -> (Cx -> IO ()) -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [Cx]
cxs ((Cx -> IO ()) -> IO ()) -> (Cx -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \cx :: Cx
cx@(Cx Target
target Udp
_ [OSC]
oscs AddrInfo
_ Maybe AddrInfo
_ Maybe (MVar [Int])
bussesMV) -> do
Maybe [Int]
busses <- (MVar [Int] -> IO [Int]) -> Maybe (MVar [Int]) -> IO (Maybe [Int])
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b.
Monad m =>
(a -> m b) -> Maybe a -> m (Maybe b)
mapM MVar [Int] -> IO [Int]
forall a. MVar a -> IO a
readMVar Maybe (MVar [Int])
bussesMV
let latency :: Double
latency = Target -> Double
oLatency Target
target
ms :: [(Double, Bool, Message)]
ms = (ProcessedEvent -> [(Double, Bool, Message)])
-> [ProcessedEvent] -> [(Double, Bool, Message)]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (\ProcessedEvent
e -> (OSC -> [(Double, Bool, Message)])
-> [OSC] -> [(Double, Bool, Message)]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (Maybe [Int] -> ProcessedEvent -> OSC -> [(Double, Bool, Message)]
toOSC Maybe [Int]
busses ProcessedEvent
e) [OSC]
oscs) [ProcessedEvent]
tes
[(Double, Bool, Message)]
-> ((Double, Bool, Message) -> IO ()) -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [(Double, Bool, Message)]
ms (((Double, Bool, Message) -> IO ()) -> IO ())
-> ((Double, Bool, Message) -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \(Double, Bool, Message)
m ->
Cx -> Double -> Double -> (Double, Bool, Message) -> IO ()
send Cx
cx Double
latency Double
0 (Double, Bool, Message)
m IO () -> (SomeException -> IO ()) -> IO ()
forall e a. Exception e => IO a -> (e -> IO a) -> IO a
`E.catch` \(SomeException
e :: E.SomeException) ->
Handle -> PatId -> IO ()
hPutStrLn Handle
stderr (PatId -> IO ()) -> PatId -> IO ()
forall a b. (a -> b) -> a -> b
$ PatId
"Failed to send. Is the '" PatId -> PatId -> PatId
forall a. [a] -> [a] -> [a]
++ Target -> PatId
oName Target
target PatId -> PatId -> PatId
forall a. [a] -> [a] -> [a]
++ PatId
"' target running? " PatId -> PatId -> PatId
forall a. [a] -> [a] -> [a]
++ SomeException -> PatId
forall a. Show a => a -> PatId
show SomeException
e
ValueMap -> IO ValueMap
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ValueMap
sMap''
where
handleException :: E.SomeException -> IO ()
handleException :: SomeException -> IO ()
handleException SomeException
e = do
Handle -> PatId -> IO ()
hPutStrLn Handle
stderr (PatId -> IO ()) -> PatId -> IO ()
forall a b. (a -> b) -> a -> b
$ PatId
"Failed to Stream.doTick: " PatId -> PatId -> PatId
forall a. [a] -> [a] -> [a]
++ SomeException -> PatId
forall a. Show a => a -> PatId
show SomeException
e
Handle -> PatId -> IO ()
hPutStrLn Handle
stderr PatId
"Return to previous pattern."
MVar PlayMap -> IO ()
setPreviousPatternOrSilence MVar PlayMap
playMV
processCps :: Clock.ClockConfig -> Clock.ClockRef -> (Link.SessionState, Link.SessionState) -> [Event ValueMap] -> IO [ProcessedEvent]
processCps :: ClockConfig
-> ClockRef
-> (SessionState, SessionState)
-> [Event ValueMap]
-> IO [ProcessedEvent]
processCps ClockConfig
cconf ClockRef
cref (SessionState
ss, SessionState
temposs) = (Event ValueMap -> IO ProcessedEvent)
-> [Event ValueMap] -> IO [ProcessedEvent]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [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 :: ArcF Rational
wope = Event ValueMap -> ArcF Rational
forall a. Event a -> ArcF Rational
wholeOrPart Event ValueMap
e
partStartCycle :: Rational
partStartCycle = ArcF Rational -> Rational
forall a. ArcF a -> a
start (ArcF Rational -> Rational) -> ArcF Rational -> Rational
forall a b. (a -> b) -> a -> b
$ Event ValueMap -> ArcF Rational
forall a b. EventF a b -> a
part Event ValueMap
e
partStartBeat :: Double
partStartBeat = ClockConfig -> Double -> Double
Clock.cyclesToBeat ClockConfig
cconf (Rational -> Double
forall a b. (Real a, Fractional b) => a -> b
realToFrac Rational
partStartCycle)
onCycle :: Rational
onCycle = ArcF Rational -> Rational
forall a. ArcF a -> a
start ArcF Rational
wope
onBeat :: Double
onBeat = ClockConfig -> Double -> Double
Clock.cyclesToBeat ClockConfig
cconf (Rational -> Double
forall a b. (Real a, Fractional b) => a -> b
realToFrac Rational
onCycle)
offCycle :: Rational
offCycle = ArcF Rational -> Rational
forall a. ArcF a -> a
stop ArcF Rational
wope
offBeat :: Double
offBeat = ClockConfig -> Double -> Double
Clock.cyclesToBeat ClockConfig
cconf (Rational -> Double
forall a b. (Real a, Fractional b) => a -> b
realToFrac Rational
offCycle)
Micros
on <- ClockConfig -> SessionState -> Double -> IO Micros
Clock.timeAtBeat ClockConfig
cconf SessionState
ss Double
onBeat
Micros
onPart <- ClockConfig -> SessionState -> Double -> IO Micros
Clock.timeAtBeat ClockConfig
cconf SessionState
ss Double
partStartBeat
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when
(Event ValueMap -> Bool
forall a. Event a -> Bool
eventHasOnset Event ValueMap
e)
( do
let cps' :: Maybe Double
cps' = PatId -> ValueMap -> Maybe Value
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup PatId
"cps" (Event ValueMap -> ValueMap
forall a b. EventF a b -> b
value Event ValueMap
e) Maybe Value -> (Value -> Maybe Double) -> Maybe Double
forall a b. Maybe a -> (a -> Maybe b) -> Maybe b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Value -> Maybe Double
getF
IO () -> (Double -> IO ()) -> Maybe Double -> IO ()
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (() -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()) ((\Rational
newCps -> Rational -> Micros -> ClockConfig -> SessionState -> IO ()
Clock.setTempoCPS Rational
newCps Micros
on ClockConfig
cconf SessionState
temposs) (Rational -> IO ()) -> (Double -> Rational) -> Double -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Double -> Rational
forall a. Real a => a -> Rational
toRational) Maybe Double
cps'
)
Micros
off <- ClockConfig -> SessionState -> Double -> IO Micros
Clock.timeAtBeat ClockConfig
cconf SessionState
ss Double
offBeat
Rational
bpm <- SessionState -> IO Rational
Clock.getTempo SessionState
ss
Double
wholeOrPartOsc <- ClockRef -> Micros -> IO Double
Clock.linkToOscTime ClockRef
cref Micros
on
Double
onPartOsc <- ClockRef -> Micros -> IO Double
Clock.linkToOscTime ClockRef
cref Micros
onPart
let cps :: Double
cps = ClockConfig -> Double -> Double
Clock.beatToCycles ClockConfig
cconf (Rational -> Double
forall a. Fractional a => Rational -> a
fromRational Rational
bpm) Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
60
let delta :: Micros
delta = Micros
off Micros -> Micros -> Micros
forall a. Num a => a -> a -> a
- Micros
on
ProcessedEvent -> IO ProcessedEvent
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (ProcessedEvent -> IO ProcessedEvent)
-> ProcessedEvent -> IO ProcessedEvent
forall a b. (a -> b) -> a -> b
$!
ProcessedEvent
{ peHasOnset :: Bool
peHasOnset = Event ValueMap -> Bool
forall a. Event a -> Bool
eventHasOnset Event ValueMap
e,
peEvent :: Event ValueMap
peEvent = Event ValueMap
e,
peCps :: Double
peCps = Double
cps,
peDelta :: Micros
peDelta = Micros
delta,
peCycle :: Rational
peCycle = Rational
onCycle,
peOnWholeOrPart :: Micros
peOnWholeOrPart = Micros
on,
peOnWholeOrPartOsc :: Double
peOnWholeOrPartOsc = Double
wholeOrPartOsc,
peOnPart :: Micros
peOnPart = Micros
onPart,
peOnPartOsc :: Double
peOnPartOsc = Double
onPartOsc
}
toOSC :: Maybe [Int] -> ProcessedEvent -> OSC -> [(Double, Bool, O.Message)]
toOSC :: Maybe [Int] -> ProcessedEvent -> OSC -> [(Double, Bool, Message)]
toOSC Maybe [Int]
maybeBusses ProcessedEvent
pe osc :: OSC
osc@(OSC PatId
_ Args
_) =
[Maybe (Double, Bool, Message)] -> [(Double, Bool, Message)]
forall a. [Maybe a] -> [a]
catMaybes (Maybe (Double, Bool, Message)
playmsg Maybe (Double, Bool, Message)
-> [Maybe (Double, Bool, Message)]
-> [Maybe (Double, Bool, Message)]
forall a. a -> [a] -> [a]
: [Maybe (Double, Bool, Message)]
busmsgs)
where
(ValueMap
playmap, ValueMap
busmap) = (PatId -> Value -> Bool) -> ValueMap -> (ValueMap, ValueMap)
forall k a. (k -> a -> Bool) -> Map k a -> (Map k a, Map k a)
Map.partitionWithKey (\PatId
k Value
_ -> PatId -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null PatId
k Bool -> Bool -> Bool
|| PatId -> Char
forall a. HasCallStack => [a] -> a
head PatId
k Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
'^') (ValueMap -> (ValueMap, ValueMap))
-> ValueMap -> (ValueMap, ValueMap)
forall a b. (a -> b) -> a -> b
$ ProcessedEvent -> ValueMap
val ProcessedEvent
pe
playmap' :: ValueMap
playmap' = ValueMap -> ValueMap -> ValueMap
forall k a. Ord k => Map k a -> Map k a -> Map k a
Map.union ((PatId -> PatId) -> ValueMap -> ValueMap
forall k2 k1 a. Ord k2 => (k1 -> k2) -> Map k1 a -> Map k2 a
Map.mapKeys (Int -> PatId -> PatId
forall a. Int -> [a] -> [a]
drop Int
1) (ValueMap -> ValueMap) -> ValueMap -> ValueMap
forall a b. (a -> b) -> a -> b
$ (Value -> Value) -> ValueMap -> ValueMap
forall a b k. (a -> b) -> Map k a -> Map k b
Map.map (\Value
v -> PatId -> Value
VS (Char
'c' Char -> PatId -> PatId
forall a. a -> [a] -> [a]
: Int -> PatId
forall a. Show a => a -> PatId
show (Int -> Int
toBus (Int -> Int) -> Int -> Int
forall a b. (a -> b) -> a -> b
$ Int -> Maybe Int -> Int
forall a. a -> Maybe a -> a
fromMaybe Int
0 (Maybe Int -> Int) -> Maybe Int -> Int
forall a b. (a -> b) -> a -> b
$ Value -> Maybe Int
getI Value
v))) ValueMap
busmap) ValueMap
playmap
val :: ProcessedEvent -> ValueMap
val = Event ValueMap -> ValueMap
forall a b. EventF a b -> b
value (Event ValueMap -> ValueMap)
-> (ProcessedEvent -> Event ValueMap) -> ProcessedEvent -> ValueMap
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 =
[(PatId, Value)] -> ValueMap
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList
[ (PatId
"cps", Double -> Value
VF (ProcessedEvent -> Double
peCps ProcessedEvent
pe)),
(PatId
"delta", Double -> Value
VF (Micros -> Double -> Double
Clock.addMicrosToOsc (ProcessedEvent -> Micros
peDelta ProcessedEvent
pe) Double
0)),
(PatId
"cycle", Double -> Value
VF (Rational -> Double
forall a. Fractional a => Rational -> a
fromRational (ProcessedEvent -> Rational
peCycle ProcessedEvent
pe)))
]
addExtra :: ValueMap
addExtra = ValueMap -> ValueMap -> ValueMap
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 Double -> Double -> Double
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 = addExtra})
PatId
mungedPath <- PatId -> ValueMap -> Maybe PatId
substitutePath (OSC -> PatId
path OSC
osc) ValueMap
playmap'
(Double, Bool, Message) -> Maybe (Double, Bool, Message)
forall a. a -> Maybe a
forall (m :: * -> *) a. Monad m => a -> m a
return
( Double
ts,
Bool
False,
PatId -> [Datum] -> Message
O.Message PatId
mungedPath [Datum]
vs
)
| Bool
otherwise = Maybe (Double, Bool, Message)
forall a. Maybe a
Nothing
toBus :: Int -> Int
toBus Int
n
| Just [Int]
busses <- Maybe [Int]
maybeBusses, (Bool -> Bool
not (Bool -> Bool) -> ([Int] -> Bool) -> [Int] -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Int] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null) [Int]
busses = [Int]
busses [Int] -> Int -> Int
forall a. [a] -> Int -> a
!!! Int
n
| Bool
otherwise = Int
n
busmsgs :: [Maybe (Double, Bool, Message)]
busmsgs =
((PatId, Value) -> Maybe (Double, Bool, Message))
-> [(PatId, Value)] -> [Maybe (Double, Bool, Message)]
forall a b. (a -> b) -> [a] -> [b]
map
( \(PatId
k, Value
b) -> do
PatId
k' <- if Bool -> Bool
not (PatId -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null PatId
k) Bool -> Bool -> Bool
&& PatId -> Char
forall a. HasCallStack => [a] -> a
head PatId
k Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'^' then PatId -> Maybe PatId
forall a. a -> Maybe a
Just (Int -> PatId -> PatId
forall a. Int -> [a] -> [a]
drop Int
1 PatId
k) else Maybe PatId
forall a. Maybe a
Nothing
Value
v <- PatId -> ValueMap -> Maybe Value
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup PatId
k' ValueMap
playmap
Int
bi <- Value -> Maybe Int
getI Value
b
(Double, Bool, Message) -> Maybe (Double, Bool, Message)
forall a. a -> Maybe a
forall (m :: * -> *) a. Monad m => a -> m a
return
( Double
tsPart,
Bool
True,
PatId -> [Datum] -> Message
O.Message PatId
"/c_set" [Int -> Datum
forall n. Integral n => n -> Datum
O.int32 (Int -> Int
toBus Int
bi), Value -> Datum
toDatum Value
v]
)
)
(ValueMap -> [(PatId, Value)]
forall k a. Map k a -> [(k, a)]
Map.toList ValueMap
busmap)
where
tsPart :: Double
tsPart = ProcessedEvent -> Double
peOnPartOsc ProcessedEvent
pe Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
nudge
nudge :: Double
nudge = Maybe Double -> Double
forall a. HasCallStack => Maybe a -> a
fromJust (Maybe Double -> Double) -> Maybe Double -> Double
forall a b. (a -> b) -> a -> b
$ Value -> Maybe Double
getF (Value -> Maybe Double) -> Value -> Maybe Double
forall a b. (a -> b) -> a -> b
$ Value -> Maybe Value -> Value
forall a. a -> Maybe a -> a
fromMaybe (Double -> Value
VF Double
0) (Maybe Value -> Value) -> Maybe Value -> Value
forall a b. (a -> b) -> a -> b
$ PatId -> ValueMap -> Maybe Value
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup PatId
"nudge" ValueMap
playmap
toOSC Maybe [Int]
_ ProcessedEvent
pe (OSCContext PatId
oscpath) =
(((Int, Int), (Int, Int)) -> (Double, Bool, Message))
-> [((Int, Int), (Int, Int))] -> [(Double, Bool, Message)]
forall a b. (a -> b) -> [a] -> [b]
map ((Int, Int), (Int, Int)) -> (Double, Bool, Message)
cToM ([((Int, Int), (Int, Int))] -> [(Double, Bool, Message)])
-> [((Int, Int), (Int, Int))] -> [(Double, Bool, Message)]
forall a b. (a -> b) -> a -> b
$ Context -> [((Int, Int), (Int, Int))]
contextPosition (Context -> [((Int, Int), (Int, Int))])
-> Context -> [((Int, Int), (Int, Int))]
forall a b. (a -> b) -> a -> b
$ Event ValueMap -> Context
forall a b. EventF a b -> Context
context (Event ValueMap -> Context) -> Event ValueMap -> 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,
PatId -> [Datum] -> Message
O.Message PatId
oscpath ([Datum] -> Message) -> [Datum] -> Message
forall a b. (a -> b) -> a -> b
$ PatId -> Datum
O.string PatId
ident Datum -> [Datum] -> [Datum]
forall a. a -> [a] -> [a]
: Micros -> Datum
forall n. Real n => n -> Datum
O.float (ProcessedEvent -> Micros
peDelta ProcessedEvent
pe) Datum -> [Datum] -> [Datum]
forall a. a -> [a] -> [a]
: Double -> Datum
forall n. Real n => n -> Datum
O.float Double
cyc Datum -> [Datum] -> [Datum]
forall a. a -> [a] -> [a]
: (Int -> Datum) -> [Int] -> [Datum]
forall a b. (a -> b) -> [a] -> [b]
map Int -> Datum
forall n. Integral n => n -> Datum
O.int32 [Int
x, Int
y, Int
x', Int
y']
)
cyc :: Double
cyc :: Double
cyc = Rational -> Double
forall a. Fractional a => Rational -> a
fromRational (Rational -> Double) -> Rational -> Double
forall a b. (a -> b) -> a -> b
$ ProcessedEvent -> Rational
peCycle ProcessedEvent
pe
nudge :: Double
nudge = Double -> Maybe Double -> Double
forall a. a -> Maybe a -> a
fromMaybe Double
0 (Maybe Double -> Double) -> Maybe Double -> Double
forall a b. (a -> b) -> a -> b
$ PatId -> ValueMap -> Maybe Value
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup PatId
"nudge" (Event ValueMap -> ValueMap
forall a b. EventF a b -> b
value (Event ValueMap -> ValueMap) -> Event ValueMap -> ValueMap
forall a b. (a -> b) -> a -> b
$ ProcessedEvent -> Event ValueMap
peEvent ProcessedEvent
pe) Maybe Value -> (Value -> Maybe Double) -> Maybe Double
forall a b. Maybe a -> (a -> Maybe b) -> Maybe b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Value -> Maybe Double
getF
ident :: PatId
ident = PatId -> Maybe PatId -> PatId
forall a. a -> Maybe a -> a
fromMaybe PatId
"unknown" (Maybe PatId -> PatId) -> Maybe PatId -> PatId
forall a b. (a -> b) -> a -> b
$ PatId -> ValueMap -> Maybe Value
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup PatId
"_id_" (Event ValueMap -> ValueMap
forall a b. EventF a b -> b
value (Event ValueMap -> ValueMap) -> Event ValueMap -> ValueMap
forall a b. (a -> b) -> a -> b
$ ProcessedEvent -> Event ValueMap
peEvent ProcessedEvent
pe) Maybe Value -> (Value -> Maybe PatId) -> Maybe PatId
forall a b. Maybe a -> (a -> Maybe b) -> Maybe b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Value -> Maybe PatId
getS
ts :: Double
ts = ProcessedEvent -> Double
peOnWholeOrPartOsc ProcessedEvent
pe Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
nudge
toData :: OSC -> Event ValueMap -> Maybe [O.Datum]
toData :: OSC -> Event ValueMap -> Maybe [Datum]
toData (OSC {args :: OSC -> Args
args = ArgList [(PatId, Maybe Value)]
as}) Event ValueMap
e = ([Value] -> [Datum]) -> Maybe [Value] -> Maybe [Datum]
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((Value -> Datum) -> [Value] -> [Datum]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Value -> Datum
toDatum) (Maybe [Value] -> Maybe [Datum]) -> Maybe [Value] -> Maybe [Datum]
forall a b. (a -> b) -> a -> b
$ ((PatId, Maybe Value) -> Maybe Value)
-> [(PatId, Maybe Value)] -> Maybe [Value]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM (\(PatId
n, Maybe Value
v) -> PatId -> ValueMap -> Maybe Value
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup PatId
n (Event ValueMap -> ValueMap
forall a b. EventF a b -> b
value Event ValueMap
e) Maybe Value -> Maybe Value -> Maybe Value
forall a. Maybe a -> Maybe a -> Maybe a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Maybe Value
v) [(PatId, Maybe Value)]
as
toData (OSC {args :: OSC -> Args
args = Named [PatId]
rqrd}) Event ValueMap
e
| [PatId] -> Bool
hasRequired [PatId]
rqrd = [Datum] -> Maybe [Datum]
forall a. a -> Maybe a
Just ([Datum] -> Maybe [Datum]) -> [Datum] -> Maybe [Datum]
forall a b. (a -> b) -> a -> b
$ ((PatId, Value) -> [Datum]) -> [(PatId, Value)] -> [Datum]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (\(PatId
n, Value
v) -> [PatId -> Datum
O.string PatId
n, Value -> Datum
toDatum Value
v]) ([(PatId, Value)] -> [Datum]) -> [(PatId, Value)] -> [Datum]
forall a b. (a -> b) -> a -> b
$ ValueMap -> [(PatId, Value)]
forall k a. Map k a -> [(k, a)]
Map.toList (ValueMap -> [(PatId, Value)]) -> ValueMap -> [(PatId, Value)]
forall a b. (a -> b) -> a -> b
$ Event ValueMap -> ValueMap
forall a b. EventF a b -> b
value Event ValueMap
e
| Bool
otherwise = Maybe [Datum]
forall a. Maybe a
Nothing
where
hasRequired :: [PatId] -> Bool
hasRequired [] = Bool
True
hasRequired [PatId]
xs = (PatId -> Bool) -> [PatId] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (PatId -> [PatId] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [PatId]
ks) [PatId]
xs
ks :: [PatId]
ks = ValueMap -> [PatId]
forall k a. Map k a -> [k]
Map.keys (Event ValueMap -> ValueMap
forall a b. EventF a b -> b
value Event ValueMap
e)
toData OSC
_ Event ValueMap
_ = Maybe [Datum]
forall a. Maybe a
Nothing
toDatum :: Value -> O.Datum
toDatum :: Value -> Datum
toDatum (VF Double
x) = Double -> Datum
forall n. Real n => n -> Datum
O.float Double
x
toDatum (VN Note
x) = Note -> Datum
forall n. Real n => n -> Datum
O.float Note
x
toDatum (VI Int
x) = Int -> Datum
forall n. Integral n => n -> Datum
O.int32 Int
x
toDatum (VS PatId
x) = PatId -> Datum
O.string PatId
x
toDatum (VR Rational
x) = Double -> Datum
forall n. Real n => n -> Datum
O.float (Rational -> Double
forall a. Fractional a => Rational -> a
fromRational Rational
x :: Double)
toDatum (VB Bool
True) = Int -> Datum
forall n. Integral n => n -> Datum
O.int32 (Int
1 :: Int)
toDatum (VB Bool
False) = Int -> Datum
forall n. Integral n => n -> Datum
O.int32 (Int
0 :: Int)
toDatum (VX [Word8]
xs) = Blob -> Datum
O.Blob (Blob -> Datum) -> Blob -> Datum
forall a b. (a -> b) -> a -> b
$ [Word8] -> Blob
O.blob_pack [Word8]
xs
toDatum Value
_ = PatId -> Datum
forall a. HasCallStack => PatId -> a
error PatId
"toDatum: unhandled value"
substitutePath :: String -> ValueMap -> Maybe String
substitutePath :: PatId -> ValueMap -> Maybe PatId
substitutePath PatId
str ValueMap
cm = PatId -> Maybe PatId
parse PatId
str
where
parse :: PatId -> Maybe PatId
parse [] = PatId -> Maybe PatId
forall a. a -> Maybe a
Just []
parse (Char
'{' : PatId
xs) = PatId -> Maybe PatId
parseWord PatId
xs
parse (Char
x : PatId
xs) = do
PatId
xs' <- PatId -> Maybe PatId
parse PatId
xs
PatId -> Maybe PatId
forall a. a -> Maybe a
forall (m :: * -> *) a. Monad m => a -> m a
return (Char
x Char -> PatId -> PatId
forall a. a -> [a] -> [a]
: PatId
xs')
parseWord :: PatId -> Maybe PatId
parseWord PatId
xs
| PatId -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null PatId
b = ValueMap -> PatId -> Maybe PatId
getString ValueMap
cm PatId
a
| Bool
otherwise = do
PatId
v <- ValueMap -> PatId -> Maybe PatId
getString ValueMap
cm PatId
a
PatId
xs' <- PatId -> Maybe PatId
parse (Int -> PatId -> PatId
forall a. Int -> [a] -> [a]
drop Int
1 PatId
b)
PatId -> Maybe PatId
forall a. a -> Maybe a
forall (m :: * -> *) a. Monad m => a -> m a
return (PatId -> Maybe PatId) -> PatId -> Maybe PatId
forall a b. (a -> b) -> a -> b
$ PatId
v PatId -> PatId -> PatId
forall a. [a] -> [a] -> [a]
++ PatId
xs'
where
(PatId
a, PatId
b) = (Char -> Bool) -> PatId -> (PatId, PatId)
forall a. (a -> Bool) -> [a] -> ([a], [a])
break (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'}') PatId
xs
getString :: ValueMap -> String -> Maybe String
getString :: ValueMap -> PatId -> Maybe PatId
getString ValueMap
cm PatId
s = (Value -> PatId
simpleShow (Value -> PatId) -> Maybe Value -> Maybe PatId
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> PatId -> ValueMap -> Maybe Value
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup PatId
param ValueMap
cm) Maybe PatId -> Maybe PatId -> Maybe PatId
forall a. Maybe a -> Maybe a -> Maybe a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> PatId -> Maybe PatId
defaultValue PatId
dflt
where
(PatId
param, PatId
dflt) = (Char -> Bool) -> PatId -> (PatId, PatId)
forall a. (a -> Bool) -> [a] -> ([a], [a])
break (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'=') PatId
s
simpleShow :: Value -> String
simpleShow :: Value -> PatId
simpleShow (VS PatId
str) = PatId
str
simpleShow (VI Int
i) = Int -> PatId
forall a. Show a => a -> PatId
show Int
i
simpleShow (VF Double
f) = Double -> PatId
forall a. Show a => a -> PatId
show Double
f
simpleShow (VN Note
n) = Note -> PatId
forall a. Show a => a -> PatId
show Note
n
simpleShow (VR Rational
r) = Rational -> PatId
forall a. Show a => a -> PatId
show Rational
r
simpleShow (VB Bool
b) = Bool -> PatId
forall a. Show a => a -> PatId
show Bool
b
simpleShow (VX [Word8]
xs) = [Word8] -> PatId
forall a. Show a => a -> PatId
show [Word8]
xs
simpleShow (VState ValueMap -> (ValueMap, Value)
_) = PatId -> PatId
forall a. Show a => a -> PatId
show PatId
"<stateful>"
simpleShow (VPattern Pattern Value
_) = PatId -> PatId
forall a. Show a => a -> PatId
show PatId
"<pattern>"
simpleShow (VList [Value]
_) = PatId -> PatId
forall a. Show a => a -> PatId
show PatId
"<list>"
defaultValue :: String -> Maybe String
defaultValue :: PatId -> Maybe PatId
defaultValue (Char
'=' : PatId
dfltVal) = PatId -> Maybe PatId
forall a. a -> Maybe a
Just PatId
dfltVal
defaultValue PatId
_ = Maybe PatId
forall a. Maybe a
Nothing
playStack :: PlayMap -> ControlPattern
playStack :: PlayMap -> ControlPattern
playStack PlayMap
pMap = [ControlPattern] -> ControlPattern
forall a. [Pattern a] -> Pattern a
stack ([ControlPattern] -> ControlPattern)
-> (PlayMap -> [ControlPattern]) -> PlayMap -> ControlPattern
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (PlayState -> ControlPattern) -> [PlayState] -> [ControlPattern]
forall a b. (a -> b) -> [a] -> [b]
map PlayState -> ControlPattern
psPattern ([PlayState] -> [ControlPattern])
-> (PlayMap -> [PlayState]) -> PlayMap -> [ControlPattern]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (PlayState -> Bool) -> [PlayState] -> [PlayState]
forall a. (a -> Bool) -> [a] -> [a]
filter PlayState -> Bool
active ([PlayState] -> [PlayState])
-> (PlayMap -> [PlayState]) -> PlayMap -> [PlayState]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PlayMap -> [PlayState]
forall k a. Map k a -> [a]
Map.elems (PlayMap -> ControlPattern) -> PlayMap -> ControlPattern
forall a b. (a -> b) -> a -> b
$ PlayMap
pMap
where
active :: PlayState -> Bool
active PlayState
pState =
if PlayMap -> Bool
forall k. Map k PlayState -> Bool
hasSolo PlayMap
pMap
then PlayState -> Bool
psSolo PlayState
pState
else Bool -> Bool
not (PlayState -> Bool
psMute PlayState
pState)
hasSolo :: Map.Map k PlayState -> Bool
hasSolo :: forall k. Map k PlayState -> Bool
hasSolo = (PlayState -> Bool) -> [PlayState] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any PlayState -> Bool
psSolo ([PlayState] -> Bool)
-> (Map k PlayState -> [PlayState]) -> Map k PlayState -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Map k PlayState -> [PlayState]
forall k a. Map k a -> [a]
Map.elems
onSingleTick :: Clock.ClockConfig -> Clock.ClockRef -> MVar ValueMap -> MVar PlayMap -> MVar (ControlPattern -> ControlPattern) -> [Cx] -> ControlPattern -> IO ()
onSingleTick :: ClockConfig
-> ClockRef
-> MVar ValueMap
-> MVar PlayMap
-> MVar (ControlPattern -> ControlPattern)
-> [Cx]
-> ControlPattern
-> IO ()
onSingleTick ClockConfig
clockConfig ClockRef
clockRef MVar ValueMap
stateMV MVar PlayMap
_ MVar (ControlPattern -> ControlPattern)
globalFMV [Cx]
cxs ControlPattern
pat = do
MVar PlayMap
pMapMV <-
PlayMap -> IO (MVar PlayMap)
forall a. a -> IO (MVar a)
newMVar (PlayMap -> IO (MVar PlayMap)) -> PlayMap -> IO (MVar PlayMap)
forall a b. (a -> b) -> a -> b
$
PatId -> PlayState -> PlayMap
forall k a. k -> a -> Map k a
Map.singleton
PatId
"fake"
( PlayState
{ psPattern :: ControlPattern
psPattern = ControlPattern
pat,
psMute :: Bool
psMute = Bool
False,
psSolo :: Bool
psSolo = Bool
False,
psHistory :: [ControlPattern]
psHistory = []
}
)
((Rational, Rational)
-> Double
-> ClockConfig
-> ClockRef
-> (SessionState, SessionState)
-> IO ())
-> ClockConfig -> ClockRef -> IO ()
Clock.clockOnce (MVar ValueMap
-> MVar PlayMap
-> MVar (ControlPattern -> ControlPattern)
-> [Cx]
-> (Rational, Rational)
-> Double
-> ClockConfig
-> ClockRef
-> (SessionState, SessionState)
-> IO ()
doTick MVar ValueMap
stateMV MVar PlayMap
pMapMV MVar (ControlPattern -> ControlPattern)
globalFMV [Cx]
cxs) ClockConfig
clockConfig ClockRef
clockRef
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 = ControlPattern -> ArcF Rational -> [Event ValueMap]
forall a. Pattern a -> ArcF Rational -> [Event a]
queryArc ControlPattern
pat (Rational -> Rational -> ArcF Rational
forall a. a -> a -> ArcF a
Arc Rational
0 Rational
0)
PlayMap
pMap <- [Event ValueMap] -> IO PlayMap -> IO PlayMap
forall a b. a -> b -> b
seq [Event ValueMap]
x (IO PlayMap -> IO PlayMap) -> IO PlayMap -> IO PlayMap
forall a b. (a -> b) -> a -> b
$ MVar PlayMap -> IO PlayMap
forall a. MVar a -> IO a
takeMVar (Stream -> MVar PlayMap
sPMapMV Stream
stream)
let playState :: PlayState
playState = Maybe PlayState -> PlayState
updatePS (Maybe PlayState -> PlayState) -> Maybe PlayState -> PlayState
forall a b. (a -> b) -> a -> b
$ PatId -> PlayMap -> Maybe PlayState
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup (ID -> PatId
fromID ID
k) PlayMap
pMap
MVar PlayMap -> PlayMap -> IO ()
forall a. MVar a -> a -> IO ()
putMVar (Stream -> MVar PlayMap
sPMapMV Stream
stream) (PlayMap -> IO ()) -> PlayMap -> IO ()
forall a b. (a -> b) -> a -> b
$ PatId -> PlayState -> PlayMap -> PlayMap
forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert (ID -> PatId
fromID ID
k) PlayState
playState PlayMap
pMap
where
updatePS :: Maybe PlayState -> PlayState
updatePS (Just PlayState
playState) = do PlayState
playState {psPattern = pat', psHistory = pat : psHistory playState}
updatePS Maybe PlayState
Nothing = ControlPattern -> Bool -> Bool -> [ControlPattern] -> PlayState
PlayState ControlPattern
pat' Bool
False Bool
False [ControlPattern
pat']
patControls :: ValueMap
patControls = PatId -> Value -> ValueMap
forall k a. k -> a -> Map k a
Map.singleton PatId
patternTimeID (Rational -> Value
VR Rational
t)
pat' :: ControlPattern
pat' =
(ValueMap -> ValueMap) -> ControlPattern -> ControlPattern
forall a. (ValueMap -> ValueMap) -> Pattern a -> Pattern a
withQueryControls (ValueMap -> ValueMap -> ValueMap
forall k a. Ord k => Map k a -> Map k a -> Map k a
Map.union ValueMap
patControls) (ControlPattern -> ControlPattern)
-> ControlPattern -> ControlPattern
forall a b. (a -> b) -> a -> b
$
ControlPattern
pat ControlPattern -> ControlPattern -> ControlPattern
forall b. Unionable b => Pattern b -> Pattern b -> Pattern b
# PatId -> Pattern PatId -> ControlPattern
pS PatId
"_id_" (PatId -> Pattern PatId
forall a. a -> Pattern a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (PatId -> Pattern PatId) -> PatId -> Pattern PatId
forall a b. (a -> b) -> a -> b
$ ID -> PatId
fromID ID
k)
setPreviousPatternOrSilence :: MVar PlayMap -> IO ()
setPreviousPatternOrSilence :: MVar PlayMap -> IO ()
setPreviousPatternOrSilence MVar PlayMap
playMV =
MVar PlayMap -> (PlayMap -> IO PlayMap) -> IO ()
forall a. MVar a -> (a -> IO a) -> IO ()
modifyMVar_ MVar PlayMap
playMV ((PlayMap -> IO PlayMap) -> IO ())
-> (PlayMap -> IO PlayMap) -> IO ()
forall a b. (a -> b) -> a -> b
$
PlayMap -> IO PlayMap
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return
(PlayMap -> IO PlayMap)
-> (PlayMap -> PlayMap) -> PlayMap -> IO PlayMap
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (PlayState -> PlayState) -> PlayMap -> PlayMap
forall a b k. (a -> b) -> Map k a -> Map k b
Map.map
( \PlayState
pMap -> case PlayState -> [ControlPattern]
psHistory PlayState
pMap of
ControlPattern
_ : ControlPattern
p : [ControlPattern]
ps -> PlayState
pMap {psPattern = p, psHistory = p : ps}
[ControlPattern]
_ -> PlayState
pMap {psPattern = silence, psHistory = [silence]}
)