packages feed

vivid 0.4.2.4 → 0.5.0.0

raw patch · 31 files changed

+900/−452 lines, 31 filesdep +cerealPVP ok

version bump matches the API change (PVP)

Dependencies added: cereal

API changes (from Hackage documentation)

- Vivid.Actions: quitSCServer :: IO ()
- Vivid.Actions.IO: defineSDFromFile :: SynthDef a -> IO ()
- Vivid.Actions.IO: instance Vivid.Actions.Class.VividAction GHC.Types.IO
- Vivid.Actions.Scheduled: doScheduledAt :: Timestamp -> Scheduled a -> IO a
- Vivid.Actions.Scheduled: doScheduledIn :: Double -> Scheduled a -> IO a
- Vivid.Actions.Scheduled: doScheduledNow :: Scheduled a -> IO a
- Vivid.NoPlugins: (&) :: () => a -> (a -> b) -> b
- Vivid.NoPlugins: Timestamp :: Double -> Timestamp
- Vivid.NoPlugins: addSecs :: Timestamp -> Double -> Timestamp
- Vivid.NoPlugins: b2i :: KnownSymbol a => BufferId -> I a
- Vivid.NoPlugins: bToI :: KnownSymbol a => BufferId -> I a
- Vivid.NoPlugins: bufToI :: KnownSymbol a => BufferId -> I a
- Vivid.NoPlugins: class Random a
- Vivid.NoPlugins: class RandomGen g
- Vivid.NoPlugins: class Uniform a
- Vivid.NoPlugins: class UniformRange a
- Vivid.NoPlugins: data AddParams a b
- Vivid.NoPlugins: data ByteString
- Vivid.NoPlugins: data NoDefaults (args :: [Symbol])
- Vivid.NoPlugins: data StdGen
- Vivid.NoPlugins: data Timestamp
- Vivid.NoPlugins: data UA (name :: Symbol) (args :: [Symbol])
- Vivid.NoPlugins: genByteString :: RandomGen g => Int -> g -> (ByteString, g)
- Vivid.NoPlugins: genRange :: RandomGen g => g -> (Int, Int)
- Vivid.NoPlugins: genShortByteString :: RandomGen g => Int -> g -> (ShortByteString, g)
- Vivid.NoPlugins: genWord16 :: RandomGen g => g -> (Word16, g)
- Vivid.NoPlugins: genWord32 :: RandomGen g => g -> (Word32, g)
- Vivid.NoPlugins: genWord32R :: RandomGen g => Word32 -> g -> (Word32, g)
- Vivid.NoPlugins: genWord64 :: RandomGen g => g -> (Word64, g)
- Vivid.NoPlugins: genWord64R :: RandomGen g => Word64 -> g -> (Word64, g)
- Vivid.NoPlugins: genWord8 :: RandomGen g => g -> (Word8, g)
- Vivid.NoPlugins: getStdGen :: MonadIO m => m StdGen
- Vivid.NoPlugins: getStdRandom :: MonadIO m => (StdGen -> (a, StdGen)) -> m a
- Vivid.NoPlugins: infixl 1 &
- Vivid.NoPlugins: infixl 9 `AddParams`
- Vivid.NoPlugins: mkStdGen :: Int -> StdGen
- Vivid.NoPlugins: newStdGen :: MonadIO m => m StdGen
- Vivid.NoPlugins: next :: RandomGen g => g -> (Int, g)
- Vivid.NoPlugins: none :: NoDefaults args
- Vivid.NoPlugins: random :: (Random a, RandomGen g) => g -> (a, g)
- Vivid.NoPlugins: randomIO :: (Random a, MonadIO m) => m a
- Vivid.NoPlugins: randomR :: (Random a, RandomGen g) => (a, a) -> g -> (a, g)
- Vivid.NoPlugins: randomRIO :: (Random a, MonadIO m) => (a, a) -> m a
- Vivid.NoPlugins: randomRs :: (Random a, RandomGen g) => (a, a) -> g -> [a]
- Vivid.NoPlugins: randoms :: (Random a, RandomGen g) => g -> [a]
- Vivid.NoPlugins: setStdGen :: MonadIO m => StdGen -> m ()
- Vivid.NoPlugins: split :: RandomGen g => g -> (g, g)
- Vivid.NoPlugins: type family SDBodyArgs a :: [Symbol]
- Vivid.NoPlugins: uniformR :: (RandomGen g, UniformRange a) => (a, a) -> g -> (a, g)
- Vivid.SCServer: closeSCServerConnection :: IO ()
- Vivid.SCServer: createSCServerConnection :: SCConnectConfig -> IO (Either String Socket)
- Vivid.SCServer.Connection: closeSCServerConnection :: IO ()
- Vivid.SCServer.Connection: createSCServerConnection :: SCConnectConfig -> IO (Either String Socket)
- Vivid.SCServer.Connection: getMailboxForSyncId :: SyncId -> IO (MVar ())
- Vivid.SCServer.Connection: getSCServerSocket :: IO Socket
- Vivid.SCServer.Connection: instance GHC.Classes.Eq Vivid.SCServer.Connection.ConnProtocol
- Vivid.SCServer.Connection: instance GHC.Classes.Ord Vivid.SCServer.Connection.ConnProtocol
- Vivid.SCServer.Connection: instance GHC.Read.Read Vivid.SCServer.Connection.ConnProtocol
- Vivid.SCServer.Connection: instance GHC.Show.Show Vivid.SCServer.Connection.ConnProtocol
- Vivid.SCServer.Connection: waitForSync_io :: SyncId -> IO ()
- Vivid.SCServer.Connection: waitForSync_io_noGC :: SyncId -> IO ()
- Vivid.SCServer.State: getNextAvailable :: (SCServerState -> TVar [a]) -> IO a
- Vivid.SCServer.State: scServerState :: SCServerState
- Vivid.SCServer.State: setClientId :: Int32 -> IO ()
- Vivid.SCServer.State: setMaxBufferIds :: Int32 -> IO ()
- Vivid.SynthDef.FromUA: instance (args0 Data.Type.Equality.~ args1, GHC.TypeLits.KnownSymbol a) => Vivid.SynthDef.FromUA.FromUA (Vivid.SynthDef.FromUA.UA a args0, Vivid.SynthDef.FromUA.UA b args1)
- Vivid.SynthDef.ToSig: instance (a Data.Type.Equality.~ args) => Vivid.SynthDef.ToSig.ToSig (Vivid.SynthDef.Types.SDBody' a Vivid.SynthDef.Types.Signal) args
+ Vivid.Actions: class MonoOrPoly s
+ Vivid.Actions: quitSCServerWith :: SCServerState -> IO ()
+ Vivid.Actions.IO: defineSDFromFileWith :: SCServerState -> SynthDef a -> IO ()
+ Vivid.Actions.IO: instance Vivid.Actions.Class.VividAction (Control.Monad.Trans.Reader.ReaderT Vivid.SCServer.State.SCServerState GHC.Types.IO)
+ Vivid.Actions.NRT: encodeNRTScore :: NRT x -> IO ByteString
+ Vivid.Actions.Scheduled: doScheduledAtWith :: SCServerState -> Timestamp -> Scheduled a -> IO a
+ Vivid.Actions.Scheduled: doScheduledInWith :: SCServerState -> Double -> Scheduled x -> IO x
+ Vivid.Actions.Scheduled: doScheduledNowWith :: SCServerState -> Scheduled x -> IO x
+ Vivid.GlobalState: closeSCServerConnection :: IO ()
+ Vivid.GlobalState: connectToSCServer :: SCConnectConfig -> IO (Socket, ThreadId)
+ Vivid.GlobalState: createSCServerConnection :: SCConnectConfig -> IO (Either String Socket)
+ Vivid.GlobalState: defineSDFromFile :: SynthDef a -> IO ()
+ Vivid.GlobalState: doScheduledAt :: Timestamp -> Scheduled a -> IO a
+ Vivid.GlobalState: doScheduledIn :: Double -> Scheduled a -> IO a
+ Vivid.GlobalState: doScheduledNow :: Scheduled a -> IO a
+ Vivid.GlobalState: getMailboxForSyncId :: SyncId -> IO (MVar ())
+ Vivid.GlobalState: getNextAvailable :: (SCServerState -> TVar [a]) -> IO a
+ Vivid.GlobalState: getNextAvailables :: Int -> (SCServerState -> TVar [a]) -> IO [a]
+ Vivid.GlobalState: getSCServerSocket :: IO Socket
+ Vivid.GlobalState: instance Vivid.Actions.Class.VividAction GHC.Types.IO
+ Vivid.GlobalState: quitSCServer :: IO ()
+ Vivid.GlobalState: setClientId :: Int32 -> IO ()
+ Vivid.GlobalState: setMaxBufferIds :: Int32 -> IO ()
+ Vivid.GlobalState: startMailbox :: Socket -> IO ()
+ Vivid.GlobalState: waitForSync_io :: SyncId -> IO ()
+ Vivid.GlobalState: waitForSync_io_noGC :: SyncId -> IO ()
+ Vivid.GlobalState: withGlobalSCServerState :: (SCServerState -> x) -> x
+ Vivid.NoPluginsNoGlobalState: (&) :: a -> (a -> b) -> b
+ Vivid.NoPluginsNoGlobalState: Timestamp :: Double -> Timestamp
+ Vivid.NoPluginsNoGlobalState: addSecs :: Timestamp -> Double -> Timestamp
+ Vivid.NoPluginsNoGlobalState: b2i :: KnownSymbol a => BufferId -> I a
+ Vivid.NoPluginsNoGlobalState: bToI :: KnownSymbol a => BufferId -> I a
+ Vivid.NoPluginsNoGlobalState: bufToI :: KnownSymbol a => BufferId -> I a
+ Vivid.NoPluginsNoGlobalState: class Random a
+ Vivid.NoPluginsNoGlobalState: class RandomGen g
+ Vivid.NoPluginsNoGlobalState: class Uniform a
+ Vivid.NoPluginsNoGlobalState: class UniformRange a
+ Vivid.NoPluginsNoGlobalState: data AddParams a b
+ Vivid.NoPluginsNoGlobalState: data ByteString
+ Vivid.NoPluginsNoGlobalState: data NoDefaults (args :: [Symbol])
+ Vivid.NoPluginsNoGlobalState: data StdGen
+ Vivid.NoPluginsNoGlobalState: data Timestamp
+ Vivid.NoPluginsNoGlobalState: data UA (name :: Symbol) (args :: [Symbol])
+ Vivid.NoPluginsNoGlobalState: genByteString :: RandomGen g => Int -> g -> (ByteString, g)
+ Vivid.NoPluginsNoGlobalState: genRange :: RandomGen g => g -> (Int, Int)
+ Vivid.NoPluginsNoGlobalState: genShortByteString :: RandomGen g => Int -> g -> (ShortByteString, g)
+ Vivid.NoPluginsNoGlobalState: genWord16 :: RandomGen g => g -> (Word16, g)
+ Vivid.NoPluginsNoGlobalState: genWord32 :: RandomGen g => g -> (Word32, g)
+ Vivid.NoPluginsNoGlobalState: genWord32R :: RandomGen g => Word32 -> g -> (Word32, g)
+ Vivid.NoPluginsNoGlobalState: genWord64 :: RandomGen g => g -> (Word64, g)
+ Vivid.NoPluginsNoGlobalState: genWord64R :: RandomGen g => Word64 -> g -> (Word64, g)
+ Vivid.NoPluginsNoGlobalState: genWord8 :: RandomGen g => g -> (Word8, g)
+ Vivid.NoPluginsNoGlobalState: getStdGen :: MonadIO m => m StdGen
+ Vivid.NoPluginsNoGlobalState: getStdRandom :: MonadIO m => (StdGen -> (a, StdGen)) -> m a
+ Vivid.NoPluginsNoGlobalState: infixl 1 &
+ Vivid.NoPluginsNoGlobalState: infixl 9 `AddParams`
+ Vivid.NoPluginsNoGlobalState: mkStdGen :: Int -> StdGen
+ Vivid.NoPluginsNoGlobalState: newStdGen :: MonadIO m => m StdGen
+ Vivid.NoPluginsNoGlobalState: next :: RandomGen g => g -> (Int, g)
+ Vivid.NoPluginsNoGlobalState: none :: NoDefaults args
+ Vivid.NoPluginsNoGlobalState: random :: (Random a, RandomGen g) => g -> (a, g)
+ Vivid.NoPluginsNoGlobalState: randomIO :: (Random a, MonadIO m) => m a
+ Vivid.NoPluginsNoGlobalState: randomR :: (Random a, RandomGen g) => (a, a) -> g -> (a, g)
+ Vivid.NoPluginsNoGlobalState: randomRIO :: (Random a, MonadIO m) => (a, a) -> m a
+ Vivid.NoPluginsNoGlobalState: randomRs :: (Random a, RandomGen g) => (a, a) -> g -> [a]
+ Vivid.NoPluginsNoGlobalState: randoms :: (Random a, RandomGen g) => g -> [a]
+ Vivid.NoPluginsNoGlobalState: setStdGen :: MonadIO m => StdGen -> m ()
+ Vivid.NoPluginsNoGlobalState: split :: RandomGen g => g -> (g, g)
+ Vivid.NoPluginsNoGlobalState: type family SDBodyArgs a :: [Symbol]
+ Vivid.NoPluginsNoGlobalState: uniformR :: (RandomGen g, UniformRange a) => (a, a) -> g -> (a, g)
+ Vivid.SCServer: [_scConnectConfig_password] :: SCConnectConfig -> Maybe ByteString
+ Vivid.SCServer: closeSCServerConnection' :: SCServerState -> IO ()
+ Vivid.SCServer: createSCServerConnection' :: SCServerState -> SCConnectConfig -> IO (Either String Socket)
+ Vivid.SCServer.Connection: ConnProtocol_TCP :: ConnProtocol
+ Vivid.SCServer.Connection: [_scConnectConfig_password] :: SCConnectConfig -> Maybe ByteString
+ Vivid.SCServer.Connection: closeSCServerConnection' :: SCServerState -> IO ()
+ Vivid.SCServer.Connection: connectToSCServer' :: SCServerState -> SCConnectConfig -> IO (Socket, ThreadId)
+ Vivid.SCServer.Connection: createSCServerConnection' :: SCServerState -> SCConnectConfig -> IO (Either String Socket)
+ Vivid.SCServer.Connection: getMailboxForSyncId' :: SCServerState -> SyncId -> IO (MVar ())
+ Vivid.SCServer.Connection: getSCServerSocket' :: SCServerState -> IO Socket
+ Vivid.SCServer.Connection: sendMaybePad :: ConnProtocol -> Socket -> ByteString -> IO ()
+ Vivid.SCServer.Connection: splitMessagesFromChunk :: ByteString -> Either String [ByteString]
+ Vivid.SCServer.Connection: startMailbox' :: SCServerState -> Socket -> IO ()
+ Vivid.SCServer.Connection: waitForSync_io' :: SCServerState -> SyncId -> IO ()
+ Vivid.SCServer.Connection: waitForSync_io_noGC' :: SCServerState -> SyncId -> IO ()
+ Vivid.SCServer.State: ConnProtocol_TCP :: ConnProtocol
+ Vivid.SCServer.State: ConnProtocol_UDP :: ConnProtocol
+ Vivid.SCServer.State: [_scServerState_connProtocol] :: SCServerState -> TVar ConnProtocol
+ Vivid.SCServer.State: data ConnProtocol
+ Vivid.SCServer.State: getNextAvailable' :: SCServerState -> (SCServerState -> TVar [a]) -> IO a
+ Vivid.SCServer.State: getNextAvailables' :: SCServerState -> Int -> (SCServerState -> TVar [a]) -> IO [a]
+ Vivid.SCServer.State: instance GHC.Classes.Eq Vivid.SCServer.State.ConnProtocol
+ Vivid.SCServer.State: instance GHC.Classes.Ord Vivid.SCServer.State.ConnProtocol
+ Vivid.SCServer.State: instance GHC.Read.Read Vivid.SCServer.State.ConnProtocol
+ Vivid.SCServer.State: instance GHC.Show.Show Vivid.SCServer.State.ConnProtocol
+ Vivid.SCServer.State: makeEmptySCServerState :: IO SCServerState
+ Vivid.SCServer.State: setServerClientId :: SCServerState -> Int32 -> IO ()
+ Vivid.SCServer.State: setServerMaxBufferIds :: SCServerState -> Int32 -> IO ()
+ Vivid.SynthDef: addOrIncrementMaxLocalBufs :: SDBody' args Signal
+ Vivid.SynthDef.FromUA: instance (args0 GHC.Types.~ args1, GHC.TypeLits.KnownSymbol a) => Vivid.SynthDef.FromUA.FromUA (Vivid.SynthDef.FromUA.UA a args0, Vivid.SynthDef.FromUA.UA b args1)
+ Vivid.SynthDef.ToSig: instance (a GHC.Types.~ args) => Vivid.SynthDef.ToSig.ToSig (Vivid.SynthDef.Types.SDBody' a Vivid.SynthDef.Types.Signal) args
+ Vivid.SynthDef.ToSig: instance Vivid.SynthDef.ToSig.ToSig GHC.Int.Int16 args
+ Vivid.SynthDef.ToSig: instance Vivid.SynthDef.ToSig.ToSig GHC.Int.Int32 args
+ Vivid.SynthDef.ToSig: instance Vivid.SynthDef.ToSig.ToSig GHC.Int.Int64 args
+ Vivid.SynthDef.ToSig: instance Vivid.SynthDef.ToSig.ToSig GHC.Int.Int8 args
+ Vivid.SynthDef.ToSig: instance Vivid.SynthDef.ToSig.ToSig GHC.Natural.Natural args
+ Vivid.SynthDef.ToSig: instance Vivid.SynthDef.ToSig.ToSig GHC.Real.Rational args
+ Vivid.SynthDef.ToSig: instance Vivid.SynthDef.ToSig.ToSig GHC.Types.Word args
+ Vivid.SynthDef.ToSig: instance Vivid.SynthDef.ToSig.ToSig GHC.Word.Word16 args
+ Vivid.SynthDef.ToSig: instance Vivid.SynthDef.ToSig.ToSig GHC.Word.Word32 args
+ Vivid.SynthDef.ToSig: instance Vivid.SynthDef.ToSig.ToSig GHC.Word.Word64 args
+ Vivid.SynthDef.ToSig: instance Vivid.SynthDef.ToSig.ToSig GHC.Word.Word8 args
+ Vivid.UGens.Args: decayScale_ :: ToSig s as => s -> UA "decayScale" as
+ Vivid.UGens.Args: decayscale_ :: ToSig s as => s -> UA "decayScale" as
+ Vivid.UGens.Args: freqOffset_ :: ToSig s as => s -> UA "freqOffset" as
+ Vivid.UGens.Args: freqScale_ :: ToSig s as => s -> UA "freqScale" as
+ Vivid.UGens.Args: freqoffset_ :: ToSig s as => s -> UA "freqOffset" as
+ Vivid.UGens.Args: freqscale_ :: ToSig s as => s -> UA "freqScale" as
+ Vivid.UGens.Buffer: playBufPoly :: Args '["buf"] '["rate", "trigger", "startPos", "loop", "doneAction"] a => Int -> a -> SDBody a [Signal]
+ Vivid.UGens.Buffer: recordBufPoly :: Args '["buf", "in"] '["offset", "recLevel", "preLevel", "run", "loop", "trigger", "doneAction"] a => Int -> a -> SDBody a [Signal]
+ Vivid.UGens.FFT: pv_add :: (ToSig bufA as, ToSig bufB as) => bufA -> bufB -> SDBody' as Signal
+ Vivid.UGens.FFT: pv_copy :: (ToSig bufA as, ToSig bufB as) => bufA -> bufB -> SDBody' as Signal
+ Vivid.UGens.FFT: pv_copyPhase :: (ToSig bufA as, ToSig bufB as) => bufA -> bufB -> SDBody' as Signal
+ Vivid.UGens.FFT: pv_div :: (ToSig bufA as, ToSig bufB as) => bufA -> bufB -> SDBody' as Signal
+ Vivid.UGens.FFT: pv_max :: (ToSig bufA as, ToSig bufB as) => bufA -> bufB -> SDBody' as Signal
+ Vivid.UGens.FFT: pv_min :: (ToSig bufA as, ToSig bufB as) => bufA -> bufB -> SDBody' as Signal
+ Vivid.UGens.FFT: pv_mul :: (ToSig bufA as, ToSig bufB as) => bufA -> bufB -> SDBody' as Signal
- Vivid.Actions.NRT: type NRT = StateT (Timestamp, Maximum Timestamp, Map Timestamp [Either ByteString OSC]) IO
+ Vivid.Actions.NRT: type NRT = StateT NRTState IO
- Vivid.Actions.Scheduled: type Scheduled = StateT Timestamp IO
+ Vivid.Actions.Scheduled: type Scheduled = ReaderT SCServerState (StateT Timestamp IO)
- Vivid.Envelopes: EnvLiterally :: initial -> Maybe Int -> Float -> Maybe Int -> [EnvSegment] -> EnvLiterally
+ Vivid.Envelopes: EnvLiterally :: initial -> Maybe Int -> Float -> Maybe Int -> [EnvSegment] -> EnvLiterally (args :: [Symbol])
- Vivid.Envelopes: [_envLiterally_curveSegments] :: EnvLiterally -> [EnvSegment]
+ Vivid.Envelopes: [_envLiterally_curveSegments] :: EnvLiterally (args :: [Symbol]) -> [EnvSegment]
- Vivid.Envelopes: [_envLiterally_initialVal] :: EnvLiterally -> initial
+ Vivid.Envelopes: [_envLiterally_initialVal] :: EnvLiterally (args :: [Symbol]) -> initial
- Vivid.Envelopes: [_envLiterally_loopNode] :: EnvLiterally -> Maybe Int
+ Vivid.Envelopes: [_envLiterally_loopNode] :: EnvLiterally (args :: [Symbol]) -> Maybe Int
- Vivid.Envelopes: [_envLiterally_offset] :: EnvLiterally -> Float
+ Vivid.Envelopes: [_envLiterally_offset] :: EnvLiterally (args :: [Symbol]) -> Float
- Vivid.Envelopes: [_envLiterally_releaseNode] :: EnvLiterally -> Maybe Int
+ Vivid.Envelopes: [_envLiterally_releaseNode] :: EnvLiterally (args :: [Symbol]) -> Maybe Int
- Vivid.Envelopes: env :: Float -> [(Float, Float)] -> EnvCurve -> EnvLiterally a
+ Vivid.Envelopes: env :: Float -> [(Float, Float)] -> EnvCurve -> EnvLiterally args
- Vivid.SCServer: SCConnectConfig :: HostName -> ServiceName -> Int32 -> ConnProtocol -> (OSC -> IO ()) -> SCConnectConfig
+ Vivid.SCServer: SCConnectConfig :: HostName -> ServiceName -> Int32 -> ConnProtocol -> Maybe ByteString -> (OSC -> IO ()) -> SCConnectConfig
- Vivid.SCServer: Synth :: NodeId -> Synth
+ Vivid.SCServer: Synth :: NodeId -> Synth (args :: [Symbol])
- Vivid.SCServer: [_unSynth] :: Synth -> NodeId
+ Vivid.SCServer: [_unSynth] :: Synth (args :: [Symbol]) -> NodeId
- Vivid.SCServer.Connection: SCConnectConfig :: HostName -> ServiceName -> Int32 -> ConnProtocol -> (OSC -> IO ()) -> SCConnectConfig
+ Vivid.SCServer.Connection: SCConnectConfig :: HostName -> ServiceName -> Int32 -> ConnProtocol -> Maybe ByteString -> (OSC -> IO ()) -> SCConnectConfig
- Vivid.SCServer.State: SCServerState :: TVar Bool -> !TMVar Socket -> !TMVar ThreadId -> !TVar [BufferId] -> !TVar Int32 -> !TVar [NodeId] -> !TVar [SyncId] -> !TVar (Map SyncId (MVar ())) -> !TVar (OSC -> IO ()) -> !TVar (Set (SDName, Int)) -> SCServerState
+ Vivid.SCServer.State: SCServerState :: TVar Bool -> !TMVar Socket -> !TMVar ThreadId -> !TVar [BufferId] -> !TVar Int32 -> !TVar [NodeId] -> !TVar [SyncId] -> !TVar (Map SyncId (MVar ())) -> !TVar (OSC -> IO ()) -> !TVar (Set (SDName, Int)) -> TVar ConnProtocol -> SCServerState
- Vivid.SCServer.Types: Synth :: NodeId -> Synth
+ Vivid.SCServer.Types: Synth :: NodeId -> Synth (args :: [Symbol])
- Vivid.SCServer.Types: [_unSynth] :: Synth -> NodeId
+ Vivid.SCServer.Types: [_unSynth] :: Synth (args :: [Symbol]) -> NodeId
- Vivid.SynthDef: SynthDef :: SDName -> [(ByteString, Float)] -> Map Int UGen -> SynthDef
+ Vivid.SynthDef: SynthDef :: SDName -> [(ByteString, Float)] -> Map Int UGen -> SynthDef (args :: [Symbol])
- Vivid.SynthDef: [_sdName] :: SynthDef -> SDName
+ Vivid.SynthDef: [_sdName] :: SynthDef (args :: [Symbol]) -> SDName
- Vivid.SynthDef: [_sdParams] :: SynthDef -> [(ByteString, Float)]
+ Vivid.SynthDef: [_sdParams] :: SynthDef (args :: [Symbol]) -> [(ByteString, Float)]
- Vivid.SynthDef: [_sdUGens] :: SynthDef -> Map Int UGen
+ Vivid.SynthDef: [_sdUGens] :: SynthDef (args :: [Symbol]) -> Map Int UGen
- Vivid.SynthDef: execState :: () => State s a -> s -> s
+ Vivid.SynthDef: execState :: State s a -> s -> s
- Vivid.SynthDef.FromUA: NoDefaults :: NoDefaults
+ Vivid.SynthDef.FromUA: NoDefaults :: NoDefaults (args :: [Symbol])
- Vivid.SynthDef.FromUA: UA :: SDBody' args Signal -> UA
+ Vivid.SynthDef.FromUA: UA :: SDBody' args Signal -> UA (name :: Symbol) (args :: [Symbol])
- Vivid.SynthDef.Types: SynthDef :: SDName -> [(ByteString, Float)] -> Map Int UGen -> SynthDef
+ Vivid.SynthDef.Types: SynthDef :: SDName -> [(ByteString, Float)] -> Map Int UGen -> SynthDef (args :: [Symbol])
- Vivid.SynthDef.Types: [_sdName] :: SynthDef -> SDName
+ Vivid.SynthDef.Types: [_sdName] :: SynthDef (args :: [Symbol]) -> SDName
- Vivid.SynthDef.Types: [_sdParams] :: SynthDef -> [(ByteString, Float)]
+ Vivid.SynthDef.Types: [_sdParams] :: SynthDef (args :: [Symbol]) -> [(ByteString, Float)]
- Vivid.SynthDef.Types: [_sdUGens] :: SynthDef -> Map Int UGen
+ Vivid.SynthDef.Types: [_sdUGens] :: SynthDef (args :: [Symbol]) -> Map Int UGen
- Vivid.SynthDef.TypesafeArgs: I :: Float -> I
+ Vivid.SynthDef.TypesafeArgs: I :: Float -> I (x :: Symbol)
- Vivid.SynthDef.TypesafeArgs: V :: Variable
+ Vivid.SynthDef.TypesafeArgs: V :: Variable (a :: Symbol)
- Vivid.SynthDef.TypesafeArgs: VarSet :: VarSet
+ Vivid.SynthDef.TypesafeArgs: VarSet :: VarSet (s :: [Symbol])
- Vivid.SynthDef.TypesafeArgs: Vs :: Vs
+ Vivid.SynthDef.TypesafeArgs: Vs :: Vs (a :: [Symbol])
- Vivid.UGens.Envelopes: percGen :: Args '[] '["attackSecs", "releaseSecs", "level", "curve", "doneAction"] a => a -> SDBody a Signal
+ Vivid.UGens.Envelopes: percGen :: Args '[] '["attackSecs", "releaseSecs", "level", "curve", "doneAction", "gate", "fadeSecs"] a => a -> SDBody a Signal
- Vivid.UGens.Filters.Linear: klank :: Args '["in"] '[] a => a -> [(Float, Float, Float)] -> SDBody a Signal
+ Vivid.UGens.Filters.Linear: klank :: (Args '["in"] '["freqScale", "freqOffset", "decayScale"] a, ToSig freq (SDBodyArgs a), ToSig amp (SDBodyArgs a), ToSig ring (SDBodyArgs a)) => a -> [(freq, amp, ring)] -> SDBody a Signal

Files

Vivid.hs view
@@ -1,7 +1,10 @@ {-# LANGUAGE NoMonomorphismRestriction #-}  module Vivid (-     module Vivid.NoPlugins+     module Vivid.NoPluginsNoGlobalState+   , module Vivid.GlobalState    ) where -import Vivid.NoPlugins+import Vivid.NoPluginsNoGlobalState+import Vivid.GlobalState+
Vivid/Actions.hs view
@@ -5,9 +5,12 @@ --        The timing is precise, unlike IO --   - "Vivid.Actions.NRT" : non-realtime. Writes to an audio file -{-# LANGUAGE DataKinds #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE ViewPatterns #-}+{-# LANGUAGE+     DataKinds+   , OverloadedStrings+   , ViewPatterns+   #-}+   -- , Safe  {-# LANGUAGE NoIncoherentInstances #-} {-# LANGUAGE NoMonomorphismRestriction #-}@@ -50,36 +53,36 @@    , release    , releaseIn    , freeBuf-   , quitSCServer+   , quitSCServerWith    , module Vivid.Actions.Class    -- , module Vivid.Actions.IO    , module Vivid.Actions.NRT    , module Vivid.Actions.Scheduled     , makeSynth++   , MonoOrPoly -- TODO: export?    ) where  import Vivid.OSC import qualified Vivid.SC.Server.Commands as SCCmd import Vivid.SC.Server.Types import Vivid.SC.SynthDef.Types (CalculationRate(..))-import Vivid.SC.Server.Types  import Vivid.Actions.Class import Vivid.Actions.IO () import Vivid.Actions.NRT import Vivid.Actions.Scheduled-import Vivid.SCServer.Connection (closeSCServerConnection)-import Vivid.SCServer (defaultGroup)+import Vivid.SCServer (defaultGroup, SCServerState)+import Vivid.SCServer.Connection (closeSCServerConnection') import Vivid.SCServer.Types import Vivid.SynthDef (getSDHashName, sd {- , SDBody -}) -- SynthDef(..), SDBody, Signal) -- import Vivid.SynthDef.Types (SDName(..)) import Vivid.SynthDef.TypesafeArgs -import Control.Arrow (first) -- , second)+import Control.Monad.Reader (runReaderT) import qualified Data.ByteString.UTF8 as UTF8 import Data.ByteString (ByteString)-import Data.Int import Data.Monoid  -- for "play":@@ -309,10 +312,10 @@ synthAfter = newSynthAfter  -- | Stop the SuperCollider server-quitSCServer :: IO ()-quitSCServer = do-   callOSC $ SCCmd.quit-   closeSCServerConnection+quitSCServerWith :: SCServerState -> IO ()+quitSCServerWith serverState = do+   runReaderT (callOSC SCCmd.quit) serverState+   closeSCServerConnection' serverState  -- | Synchronous freeBuf :: VividAction m => BufferId -> m ()
Vivid/Actions/Class.hs view
@@ -5,8 +5,10 @@ --   upcoming versions (as early as the next release) - so don't get used --   to it! -{-# LANGUAGE KindSignatures #-}-{-# LANGUAGE Rank2Types #-}+{-# LANGUAGE+     KindSignatures+   , Rank2Types+   #-}  {-# LANGUAGE NoIncoherentInstances #-} {-# LANGUAGE NoMonomorphismRestriction #-}@@ -27,8 +29,6 @@  import Control.Monad.IO.Class (MonadIO) import Data.ByteString (ByteString)-import qualified Data.ByteString.UTF8 as UTF8-import Data.Int  class (Monad m , MonadIO m) => VividAction (m :: * -> *) where 
Vivid/Actions/IO.hs view
@@ -25,32 +25,35 @@ --  --   > playScheduledIn 0.01 playTone -{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE InstanceSigs #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TypeSynonymInstances #-}-{-# LANGUAGE ViewPatterns #-}+{-# LANGUAGE+     BangPatterns+   , InstanceSigs+   , FlexibleInstances+   , OverloadedStrings+   , TypeSynonymInstances+   , ViewPatterns+   #-}+   -- , Safe  {-# LANGUAGE NoIncoherentInstances #-} {-# LANGUAGE NoMonomorphismRestriction #-} {-# LANGUAGE NoUndecidableInstances #-}  module Vivid.Actions.IO (-     defineSDFromFile+     defineSDFromFileWith    ) where  import Vivid.Actions.Class-import Vivid.OSC (OSC(..), OSCDatum(..), encodeOSC, Timestamp(..), timestampFromUTC)--- import Vivid.SC.SynthDef.Types (CalculationRate(..))+import Vivid.OSC (OSC(..), encodeOSC, Timestamp(..), timestampFromUTC) import Vivid.SC.Server.Commands as SCCmd-import Vivid.SCServer.State (BufferId(..), NodeId(..), SyncId(..), getNextAvailable, scServerState, SCServerState(..))-import Vivid.SCServer.Connection ({-getMailboxForSyncId,-} getSCServerSocket, waitForSync_io)+import Vivid.SCServer.State (BufferId(..), NodeId(..), SyncId(..), getNextAvailable', SCServerState(..))+import Vivid.SCServer.Connection ({-getMailboxForSyncId,-} getSCServerSocket', waitForSync_io', sendMaybePad) import Vivid.SynthDef  import Control.Concurrent (forkIO, threadDelay) import Control.Concurrent.STM (readTVarIO, atomically, modifyTVar) import Control.Monad+import Control.Monad.Trans.Reader (ReaderT(..), runReaderT) import Data.ByteString (ByteString) import qualified Data.ByteString as BS (writeFile) import Data.Hashable@@ -58,22 +61,18 @@ import Data.Time (getCurrentTime) import System.Directory (getTemporaryDirectory) -import Network.Socket (withSocketsDo) -- We add this everywhere for Windows compat-import Network.Socket.ByteString (send)--instance VividAction IO where-   callOSC :: OSC -> IO ()+instance VividAction (ReaderT SCServerState IO) where+   callOSC :: OSC -> ReaderT SCServerState IO ()    callOSC message = callBS (encodeOSC message) -   callBS :: ByteString -> IO ()-   callBS message = do-      let !_ = scServerState-      sock <- getSCServerSocket-      -- TODO: if TCP, prefix with the length ("## int - the length in bytes of the following message.") from Server-Architecture.schelp-      _ <- withSocketsDo $ send sock message+   callBS :: ByteString -> ReaderT SCServerState IO ()+   callBS bs = ReaderT $ \serverState -> do+      sock <- getSCServerSocket' serverState+      connProtocol <- readTVarIO (_scServerState_connProtocol serverState)+      _ <- sendMaybePad connProtocol sock bs       return () -   sync :: IO ()+   sync :: ReaderT SCServerState IO ()    sync = do       wait (0.01 :: Float) -- Just to make sure you don't "sync" before calling                            --   the command you want to sync (temporary)@@ -81,51 +80,58 @@       callOSC $ SCCmd.sync sid       waitForSync sid -   waitForSync :: SyncId -> IO ()-   waitForSync = waitForSync_io+   waitForSync :: SyncId -> ReaderT SCServerState IO ()+   waitForSync syncId =+      ReaderT $ \serverState ->+         waitForSync_io' serverState syncId -   wait :: Real n => n -> IO ()-   wait t = threadDelay $ round (realToFrac (t * 10^(6::Int)) :: Double)+   wait :: Real n => n -> ReaderT SCServerState IO ()+   wait t = ReaderT $ \_ ->+      threadDelay $ round (realToFrac (t * 10^(6::Int)) :: Double) -   getTime :: IO Timestamp-   getTime = timestampFromUTC <$> getCurrentTime+   getTime :: ReaderT SCServerState IO Timestamp+   getTime = ReaderT $ \_ -> timestampFromUTC <$> getCurrentTime -   newBufferId :: IO BufferId-   newBufferId = do-      maxBufIds <- readTVarIO (_scServerState_maxBufIds scServerState)-      BufferId nn <- getNextAvailable _scServerState_availableBufferIds+   newBufferId :: ReaderT SCServerState IO BufferId+   newBufferId = ReaderT $ \serverState -> do+      maxBufIds <- readTVarIO (_scServerState_maxBufIds serverState)+      BufferId nn <- getNextAvailable' serverState _scServerState_availableBufferIds+      -- TODO: this 'mod' may not help anything:       return . BufferId $ nn `mod` maxBufIds -   newNodeId :: IO NodeId-   newNodeId = getNextAvailable _scServerState_availableNodeIds+   newNodeId :: ReaderT SCServerState IO NodeId+   newNodeId = ReaderT $ \serverState ->+      getNextAvailable' serverState _scServerState_availableNodeIds -   newSyncId :: IO SyncId-   newSyncId =-      getNextAvailable _scServerState_availableSyncIds+   newSyncId :: ReaderT SCServerState IO SyncId+   newSyncId = ReaderT $ \serverState ->+      getNextAvailable' serverState _scServerState_availableSyncIds -   fork :: IO () -> IO ()-   fork action = do-      _ <- forkIO action+   fork :: ReaderT SCServerState IO () -> ReaderT SCServerState IO ()+   fork action = ReaderT $ \serverState -> do+      _ <- forkIO (runReaderT action serverState)       return () -   defineSD :: SynthDef a -> IO ()-   defineSD synthDef@(SynthDef name _ _) = do-      let !_ = scServerState+   defineSD :: SynthDef a -> ReaderT SCServerState IO ()+   defineSD synthDef@(SynthDef name _ _) = ReaderT $ \serverState -> do       hasBeenDefined <- (((name, hash synthDef) `Set.member`) <$>) $-         readTVarIO (_scServerState_definedSDs scServerState)+         readTVarIO (_scServerState_definedSDs serverState)+      -- unless hasBeenDefined $ (`runReaderT` serverState) $ do+      -- unless hasBeenDefined $ (serverState runReaderT ) $ do       unless hasBeenDefined $ do-         oscWSync $ \syncId ->+         (`runReaderT` serverState) $ oscWSync $ \syncId ->             callOSC $                SCCmd.d_recv [sdToLiteral synthDef] (Just $ SCCmd.sync syncId)-         atomically $ modifyTVar (_scServerState_definedSDs scServerState) $+         atomically $ modifyTVar (_scServerState_definedSDs serverState) $             ((name, hash synthDef) `Set.insert`) +-- This could be written as ReaderT SCServerState: -- | Synchronous-defineSDFromFile :: SynthDef a -> IO ()-defineSDFromFile theSD = do+defineSDFromFileWith :: SCServerState -> SynthDef a -> IO ()+defineSDFromFileWith serverState theSD = do    tempDir <- getTemporaryDirectory    let fName = tempDir++"/" ++ show (hash theSD) ++ ".scsyndef"    BS.writeFile fName $ encodeSD theSD-   oscWSync $ \syncId ->+   (`runReaderT` serverState) $ oscWSync $ \syncId ->       callOSC $ SCCmd.d_load fName (Just $ SCCmd.sync syncId) 
Vivid/Actions/NRT.hs view
@@ -23,6 +23,7 @@      NRT -- (..) -- ^ May not be exported in the future    , writeNRT    , writeNRTScore+   , encodeNRTScore    , runNRT     , writeNRTWith@@ -33,50 +34,64 @@ import qualified Vivid.SC.Server.Commands as SCCmd  import Vivid.Actions.Class-import Vivid.Actions.IO () -- maybe not in the future import Vivid.OSC import Vivid.OSC.Bundles (encodeOSCBundles) import Vivid.SCServer -- import Vivid.SCServer.State-import Vivid.SynthDef (encodeSD, sdToLiteral)+import Vivid.SynthDef (sdToLiteral) import Vivid.SynthDef.Types  import Control.Applicative -- import Control.Arrow (first, second) import Control.Exception import Control.Monad-import Control.Monad.IO.Class (liftIO)-import Control.Monad.State (get, modify, execStateT, StateT)+import Control.Monad.State (get, modify, execStateT, StateT, state) import Data.ByteString (ByteString) import qualified Data.ByteString as BS (writeFile, hPut)-import qualified Data.ByteString.UTF8 as UTF8 import Data.Char (toLower)-import Data.Hashable (hash) import qualified Data.Map as Map import Data.Map (Map) import Data.Monoid import qualified Data.Set as Set-import System.Directory (canonicalizePath, getTemporaryDirectory, removeFile)+import System.Directory (canonicalizePath, getTemporaryDirectory) -- , removeFile) import System.Exit import System.FilePath (takeExtension) import System.IO (openBinaryTempFile, hClose) import System.Process (system) import Prelude --- We keep track of the maximum timestamp so that the generated audio file doesn't cut off before a final 'wait' finishes:-type NRT = StateT (Timestamp, Maximum Timestamp, Map Timestamp [Either ByteString OSC]) IO+data NRTState+   = NRTState {+     nrtState_now :: Timestamp+     -- We keep track of the maximum timestamp so that the generated audio file+     --   doesn't cut off before a final 'wait' finishes:+   , nrtState_maxTime :: Maximum Timestamp+   , nrtState_messages :: Map Timestamp [Either ByteString OSC]+   , nrtState_bufferIds :: [BufferId]+   , nrtState_nodeIds :: [NodeId]+   , nrtState_syncIds :: [SyncId]+   } +type NRT = StateT NRTState IO++callMessage :: Either ByteString OSC -> NRT ()+callMessage msg = do+   now <- getTime+   -- Writing it this way so that we can be crystal-clear that it's going on+   --   the end of the list (future: use dlist for efficiency):+   modify $ \ns -> ns {+        nrtState_messages =+           case Map.lookup now $ nrtState_messages ns of+              Nothing ->   Map.insert now [msg]           $ nrtState_messages ns+              Just msgs -> Map.insert now (msgs ++ [msg]) $ nrtState_messages ns+      }+ instance VividAction NRT where    callOSC :: OSC -> NRT ()-   callOSC message = do-      now <- getTime-      modify ((\f (a,b,c)->(a,b,f c)) (Map.insertWith (<>) now [Right message]))+   callOSC = callMessage . Right     callBS :: ByteString -> NRT ()-   callBS message = do-      now <- getTime-      modify $ \(a,b,x) ->-         (a, b, Map.insertWith (<>) now [Left message] x)+   callBS = callMessage . Left     sync :: NRT ()    sync = return ()@@ -85,35 +100,50 @@    waitForSync _ = return ()     wait :: Real n => n -> NRT ()-   wait t = modify $ \(oldT, maxT, c) ->-      let newT = oldT `addSecs` realToFrac t-      in (newT, Maximum newT `max` maxT, c)+   wait t = modify $ \ns ->+      let newT = nrtState_now ns `addSecs` realToFrac t+      in ns {+            nrtState_now = newT+          , nrtState_maxTime = Maximum newT `max` (nrtState_maxTime ns)+          }     getTime :: NRT Timestamp-   getTime = (\(t,_,_) -> t) <$> get+   getTime = nrtState_now <$> get     newBufferId :: NRT BufferId-   newBufferId = liftIO newBufferId+   newBufferId = state $ \ns ->+      let (x:xs) = nrtState_bufferIds ns+      in (x, ns { nrtState_bufferIds = xs})     newNodeId :: NRT NodeId-   newNodeId = liftIO newNodeId+   newNodeId = state $ \ns ->+      let (x:xs) = nrtState_nodeIds ns+      in (x, ns { nrtState_nodeIds = xs})     newSyncId :: NRT SyncId-   newSyncId = liftIO newSyncId+   newSyncId =  state $ \ns ->+      let (x:xs) = nrtState_syncIds ns+      in (x, ns { nrtState_syncIds = xs})     fork :: NRT () -> NRT ()    fork action = do-      (timeOfFork, oldMaxTime, _) <- get+      NRTState{nrtState_now=timeOfFork, nrtState_maxTime = oldMaxTime} <- get       action-      modify $ \(_timeAfterFork_ignore, newMaxTime, c) ->+      modify $ \ns -> ns {+           nrtState_now = timeOfFork            -- this 'max' probably isn't necessary:-         (timeOfFork, newMaxTime `max` oldMaxTime :: Maximum Timestamp, c)+         , nrtState_maxTime = (nrtState_maxTime ns) `max` oldMaxTime :: Maximum Timestamp+         }     defineSD :: SynthDef a -> NRT ()    defineSD synthDef = do-      modify . (\f (a,b,c)->(a,b,f c)) $ Map.insertWith mappendIfNeeded (Timestamp 0) [-           Right $ SCCmd.d_recv [sdToLiteral synthDef] Nothing-         ]+      modify $ \ns -> ns {+           nrtState_messages =+              let cmd = [+                     Right $ SCCmd.d_recv [sdToLiteral synthDef] Nothing+                   ]+              in Map.insertWith mappendIfNeeded (Timestamp 0) cmd (nrtState_messages ns)+         }     where       mappendIfNeeded :: (Ord a) {- , Monoid m)-} => [a] -> [a] -> [a]       mappendIfNeeded maybeSubset maybeSuperset =@@ -121,14 +151,47 @@             then maybeSuperset             else maybeSubset <> maybeSuperset +-- This way we can be positive that it's going to the end of the list:+_addAtTime :: Timestamp -> Either ByteString OSC -> Map Timestamp [Either ByteString OSC] -> Map Timestamp [Either ByteString OSC]+_addAtTime t msg m =+   -- Separating lookup and insert is just being extra careful that the message+   --   goes on the end:+   --   (Why do you want that? - Well, one example is if you read a buffer in+   --   at time 0 and then immediately play it. You want to read it *before*+   --   you play it :) )+   Map.insert t v m+ where+   v :: [Either ByteString OSC]+   v = case Map.lookup t m of+      Nothing -> [msg]+      Just l -> l ++ [msg] -- Could use a dlist here to snoc++ runNRT :: NRT a -> IO [OSCBundle] runNRT action = do-   (_, Maximum maxTSeen, protoBundles_woLast)-      <- execStateT action (Timestamp 0, Maximum (Timestamp 0), Map.empty)-   let protoBundles = Map.insertWith (<>) maxTSeen [] protoBundles_woLast+   result <- execStateT action startingNRTState++   let Maximum maxTSeen = nrtState_maxTime result+       protoBundles_woLast :: Map Timestamp [Either ByteString OSC]+       protoBundles_woLast = nrtState_messages result+       protoBundles = Map.insertWith (<>) maxTSeen [] protoBundles_woLast+    return [ OSCBundle t as | (t, as) <- Map.toAscList protoBundles ] +startingNRTState :: NRTState+startingNRTState = NRTState {+     nrtState_now = Timestamp 0+   , nrtState_maxTime = Maximum (Timestamp 0)+   , nrtState_messages = Map.empty+   , nrtState_bufferIds = map BufferId [0..]+   , nrtState_nodeIds = map NodeId [2..] -- TODO: make sure this is good+   , nrtState_syncIds = map SyncId [0..]+   } +encodeNRTScore :: NRT x -> IO ByteString+encodeNRTScore action =+   encodeOSCBundles <$> runNRT action+ -- | Generate a file of actions that SC can use to do NRT with. --  --   __If you just want the .aiff file, you probably want 'writeNRT' instead.__@@ -139,7 +202,7 @@ --   > scsynth -N /tmp/foo.osc _ /tmp/NRTout.aiff 44100 AIFF int16 writeNRTScore :: FilePath -> NRT a -> IO () writeNRTScore path action =-   (BS.writeFile path . encodeOSCBundles) =<< runNRT action+   BS.writeFile path =<< encodeNRTScore action   -- | Generate an audio file from an NRT action -- this can write songs far faster@@ -180,10 +243,11 @@             (".aif", "AIFF")           , (".aiff", "AIFF")           , (".wav", "WAV")+          , (".flac", "FLAC")+          , (".raw", "raw")             -- todo: these formats seem not to work.             -- Try it on more-recent versions of SC:-          -- ".flac" -> "FLAC"-          -- ".ogg" -> "vorbis"+          -- , (".ogg", "VORBIS")           ]     tempDir <- canonicalizePath =<< getTemporaryDirectory
Vivid/Actions/Scheduled.hs view
@@ -7,10 +7,12 @@ --   sure the clocks agree  -- {-# LANGUAGE BangPatterns #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE InstanceSigs #-}-{-# LANGUAGE KindSignatures #-}-{-# LANGUAGE TypeSynonymInstances #-}+{-# LANGUAGE+     FlexibleInstances+   , InstanceSigs+   , KindSignatures+   , TypeSynonymInstances+   #-} -- {-# LANGUAGE ViewPatterns #-}  {-# LANGUAGE NoIncoherentInstances #-}@@ -19,9 +21,12 @@  module Vivid.Actions.Scheduled (      Scheduled-   , doScheduledIn-   , doScheduledAt-   , doScheduledNow++   , doScheduledInWith++   , doScheduledAtWith++   , doScheduledNowWith    ) where  import Vivid.Actions.Class@@ -33,23 +38,24 @@ import Control.Concurrent import Control.Monad import Control.Monad.IO.Class (liftIO)+import Control.Monad.Trans.Reader (ReaderT, runReaderT, mapReaderT) import Control.Monad.State (evalStateT, put, get, modify, StateT) import Data.ByteString (ByteString) import Prelude -type Scheduled = StateT Timestamp IO+type Scheduled = ReaderT SCServerState (StateT Timestamp IO)   instance VividAction Scheduled where    callOSC :: OSC -> Scheduled ()    callOSC message = do       now <- getTime-      liftIO . callBS . encodeOSCBundle $ OSCBundle now [Right message]+      mapReaderT liftIO . callBS . encodeOSCBundle $ OSCBundle now [Right message]     callBS :: ByteString -> Scheduled ()    callBS message = do       now <- getTime-      liftIO . callBS . encodeOSCBundle $ OSCBundle now [Left message]+      mapReaderT liftIO . callBS . encodeOSCBundle $ OSCBundle now [Left message]     sync :: Scheduled ()    sync = return () -- always right?@@ -64,13 +70,13 @@    getTime = get     newBufferId :: Scheduled BufferId-   newBufferId = liftIO newBufferId+   newBufferId = mapReaderT liftIO (newBufferId :: ReaderT SCServerState IO BufferId)     newNodeId :: Scheduled NodeId-   newNodeId = liftIO newNodeId+   newNodeId = mapReaderT liftIO (newNodeId :: ReaderT SCServerState IO NodeId)     newSyncId :: Scheduled SyncId-   newSyncId = liftIO newSyncId+   newSyncId = mapReaderT liftIO (newSyncId :: ReaderT SCServerState IO SyncId)     fork :: Scheduled () -> Scheduled ()    fork action = do@@ -79,23 +85,24 @@       put timeOfFork     defineSD :: SynthDef a -> Scheduled ()-   defineSD = liftIO . void . forkIO . defineSD+   defineSD = mapReaderT (liftIO . void . forkIO) . defineSD  -- | Schedule an action to happen at the given time-doScheduledAt :: Timestamp -> Scheduled a -> IO a-doScheduledAt startTime action =-   evalStateT action startTime+doScheduledAtWith :: SCServerState -> Timestamp -> Scheduled a -> IO a+doScheduledAtWith serverState startTime action =+   let stateAction = runReaderT action serverState+   in evalStateT stateAction startTime  -- | Schedule an action to happen n seconds from now-doScheduledIn :: Double -> Scheduled a -> IO a-doScheduledIn numSecs action = do-   now <- getTime-   doScheduledAt (addSecs now numSecs) action+doScheduledInWith :: SCServerState -> Double -> Scheduled x -> IO x+doScheduledInWith serverState numSecs action = do+   now <- runReaderT (getTime :: ReaderT SCServerState IO Timestamp) serverState -- Not that the server state matters here+   doScheduledAtWith serverState (addSecs now numSecs) action  -- | Schedule an action to happen right now. Because of server latency this --   could arrive late, so you might want to do something like --   @doScheduledIn 0.01@ instead:-doScheduledNow :: Scheduled a -> IO a-doScheduledNow action = do-   now <- getTime-   doScheduledAt now action+doScheduledNowWith :: SCServerState -> Scheduled x -> IO x+doScheduledNowWith serverState action = do+   now <- runReaderT (getTime :: ReaderT SCServerState IO Timestamp) serverState -- Not that the server state matters here+   doScheduledAtWith serverState now action
Vivid/Envelopes.hs view
@@ -161,7 +161,7 @@    _ -> 0  -env :: Float -> [(Float, Float)] -> EnvCurve -> EnvLiterally a+env :: Float -> [(Float, Float)] -> EnvCurve -> EnvLiterally args env firstPoint pointsAndLengths curve = EnvLiterally {      _envLiterally_initialVal = firstPoint    , _envLiterally_releaseNode = Nothing
+ Vivid/GlobalState.hs view
@@ -0,0 +1,155 @@+{-# LANGUAGE+     BangPatterns+   , InstanceSigs+   #-}++module Vivid.GlobalState (+     withGlobalSCServerState+   , setClientId+   , setMaxBufferIds+   , waitForSync_io+   , waitForSync_io_noGC+   , startMailbox+   , getMailboxForSyncId+   , connectToSCServer+   , createSCServerConnection+   , closeSCServerConnection+   , getSCServerSocket+   , doScheduledIn+   , doScheduledAt+   , doScheduledNow+   , quitSCServer+   , defineSDFromFile++   -- Not sure we need to export these:+   , getNextAvailables+   , getNextAvailable+   ) where++import Control.Concurrent (ThreadId, forkIO)+import Control.Concurrent.MVar (MVar)+import Control.Concurrent.STM+import Control.Monad.Reader+import Data.ByteString (ByteString)+import Data.Int+import Network.Socket (Socket)++-- We use this only for "the unsafePerformIO hack"+-- (https://wiki.haskell.org/Top_level_mutable_state) so that functions can+-- refer to the state without being passed the state explicitly. This should+-- still be safe:+import System.IO.Unsafe (unsafePerformIO)++import Vivid.Actions (quitSCServerWith)+import Vivid.Actions.Class (VividAction(..))+import Vivid.Actions.IO (defineSDFromFileWith)+import Vivid.Actions.Scheduled+import Vivid.OSC (Timestamp)+import Vivid.SCServer.Connection+import Vivid.SCServer.State+import Vivid.SynthDef.Types (SynthDef)++{-# NOINLINE globalSCServerState #-}+globalSCServerState :: SCServerState+-- See the above note about this use of unsafePerformIO:+globalSCServerState = unsafePerformIO makeEmptySCServerState++withGlobalSCServerState :: (SCServerState -> x) -> x+withGlobalSCServerState action =+   -- This line is meant to prevent 'nested STM' errors.+   -- Would like a more systematic look at the causes.:+   let !_ = globalSCServerState++   in action globalSCServerState+++setClientId :: Int32 -> IO ()+setClientId = withGlobalSCServerState setServerClientId++setMaxBufferIds :: Int32 -> IO ()+setMaxBufferIds = withGlobalSCServerState setServerMaxBufferIds++getNextAvailable :: (SCServerState -> TVar [a]) -> IO a+getNextAvailable = withGlobalSCServerState getNextAvailable'++getNextAvailables :: Int -> (SCServerState -> TVar [a]) -> IO [a]+getNextAvailables = withGlobalSCServerState getNextAvailables'+++closeSCServerConnection :: IO ()+closeSCServerConnection = withGlobalSCServerState closeSCServerConnection'++connectToSCServer :: SCConnectConfig -> IO (Socket, ThreadId)+connectToSCServer = withGlobalSCServerState connectToSCServer'++waitForSync_io :: SyncId -> IO ()+waitForSync_io = withGlobalSCServerState waitForSync_io'++waitForSync_io_noGC :: SyncId -> IO ()+waitForSync_io_noGC = withGlobalSCServerState waitForSync_io_noGC'++startMailbox :: Socket -> IO ()+startMailbox = withGlobalSCServerState startMailbox'++getMailboxForSyncId :: SyncId -> IO (MVar ())+getMailboxForSyncId = withGlobalSCServerState getMailboxForSyncId'++createSCServerConnection :: SCConnectConfig -> IO (Either String Socket)+createSCServerConnection = withGlobalSCServerState createSCServerConnection'++getSCServerSocket :: IO Socket+getSCServerSocket = withGlobalSCServerState getSCServerSocket'++defineSDFromFile :: SynthDef a -> IO ()+defineSDFromFile = withGlobalSCServerState defineSDFromFileWith++doScheduledAt :: Timestamp -> Scheduled a -> IO a+doScheduledAt =+   withGlobalSCServerState doScheduledAtWith++doScheduledIn :: Double -> Scheduled a -> IO a+doScheduledIn =+   withGlobalSCServerState doScheduledInWith++doScheduledNow :: Scheduled a -> IO a+doScheduledNow =+   withGlobalSCServerState doScheduledNowWith++quitSCServer :: IO ()+quitSCServer = withGlobalSCServerState quitSCServerWith++instance VividAction IO where+   callBS :: ByteString -> IO ()+   callBS bs = globalIO $ callBS bs++   sync :: IO ()+   sync = globalIO sync++   waitForSync :: SyncId -> IO ()+   waitForSync syncId = globalIO $ waitForSync syncId++   wait :: Real n => n -> IO ()+   wait n = globalIO $ wait n++   getTime :: IO Timestamp+   getTime = globalIO getTime++   newBufferId :: IO BufferId+   newBufferId = globalIO newBufferId++   newNodeId :: IO NodeId+   newNodeId = globalIO newNodeId++   newSyncId :: IO SyncId+   newSyncId = globalIO newSyncId++   fork :: IO () -> IO ()+   fork = void . forkIO++   defineSD :: SynthDef a -> IO ()+   defineSD synthDef = globalIO $ defineSD synthDef++globalIO :: (ReaderT SCServerState IO x) -> IO x+globalIO action =+   withGlobalSCServerState (runReaderT action)+
+ Vivid/NoGlobalState.hs view
@@ -0,0 +1,5 @@+module Vivid.NoGlobalState (+     module Vivid.NoPluginsNoGlobalState+   ) where++import Vivid.NoPluginsNoGlobalState
Vivid/NoPlugins.hs view
@@ -1,83 +1,5 @@--- | Exports everything from Vivid (and some helpful reexports) except 'Vivid.UGens.Plugins'--{-# OPTIONS_HADDOCK show-extensions #-}--{-# LANGUAGE DataKinds #-}--{-# LANGUAGE NoRebindableSyntax #-}-{-# LANGUAGE NoIncoherentInstances #-}-{-# LANGUAGE NoMonomorphismRestriction #-}-{-# LANGUAGE NoUndecidableInstances #-}- module Vivid.NoPlugins (-   -- * Vivid Reexports-     module Vivid.Actions-   , module Vivid.Envelopes-   , module Vivid.SynthDef-   , module Vivid.UGens--   , module Vivid.SCServer-   , module Vivid.Randomness-   , addSecs-   , Timestamp(..)--   , module Vivid.SynthDef.TypesafeArgs-   , module Vivid.SynthDef.FromUA--   -- * Vivid-supercollider Reexports:-   , module Vivid.SC.SynthDef.Types--   -- * Handy Reexports For Livecoding-   --   So you need to spend as little time importing as possible while livecoding-   , module Control.Applicative-   , module Control.Monad-   , module Data.ByteString-   , module Data.Int-   , (&)-   , module Data.Monoid-   , module System.Random-   , module Control.Monad.Random-   , module Control.Monad.IO.Class---   , bufToI-   , bToI-   , b2i+     module Vivid.NoPluginsNoGlobalState    ) where --- Reexports from vivid-supercollider:-import Vivid.SC.SynthDef.Types--import Vivid.Actions-import Vivid.Envelopes-import Vivid.SCServer-import Vivid.Randomness-import Vivid.SynthDef-import Vivid.SynthDef.FromUA (Args, SDBodyArgs, UA, NoDefaults, none) -- To make type sigs not have qualified names-import Vivid.SynthDef.TypesafeArgs (AddParams)--import Vivid.UGens-import Vivid.OSC (addSecs)--import Control.Applicative-import Control.Monad-import Control.Monad.Random-import Data.ByteString (ByteString)-import Data.Function ((&))-import Data.Int-import Data.Monoid-import System.Random hiding (uniform)--import Control.Monad.IO.Class-import GHC.TypeLits----bufToI :: KnownSymbol a => BufferId -> I a-bufToI (BufferId b) = toI b--bToI :: KnownSymbol a => BufferId -> I a-bToI = bufToI--b2i :: KnownSymbol a => BufferId -> I a-b2i = bufToI+import Vivid.NoPluginsNoGlobalState
+ Vivid/NoPluginsNoGlobalState.hs view
@@ -0,0 +1,83 @@+-- | Exports everything from Vivid (and some helpful reexports) except 'Vivid.UGens.Plugins'++{-# OPTIONS_HADDOCK show-extensions #-}++{-# LANGUAGE DataKinds #-}++{-# LANGUAGE NoRebindableSyntax #-}+{-# LANGUAGE NoIncoherentInstances #-}+{-# LANGUAGE NoMonomorphismRestriction #-}+{-# LANGUAGE NoUndecidableInstances #-}++module Vivid.NoPluginsNoGlobalState (+   -- * Vivid Reexports+     module Vivid.Actions+   , module Vivid.Envelopes+   , module Vivid.SynthDef+   , module Vivid.UGens++   , module Vivid.SCServer+   , module Vivid.Randomness+   , addSecs+   , Timestamp(..)++   , module Vivid.SynthDef.TypesafeArgs+   , module Vivid.SynthDef.FromUA++   -- * Vivid-supercollider Reexports:+   , module Vivid.SC.SynthDef.Types++   -- * Handy Reexports For Livecoding+   --   So you need to spend as little time importing as possible while livecoding+   , module Control.Applicative+   , module Control.Monad+   , module Data.ByteString+   , module Data.Int+   , (&)+   , module Data.Monoid+   , module System.Random+   , module Control.Monad.Random+   , module Control.Monad.IO.Class+++   , bufToI+   , bToI+   , b2i+   ) where++-- Reexports from vivid-supercollider:+import Vivid.SC.SynthDef.Types++import Vivid.Actions+import Vivid.Envelopes+import Vivid.SCServer+import Vivid.Randomness+import Vivid.SynthDef+import Vivid.SynthDef.FromUA (Args, SDBodyArgs, UA, NoDefaults, none) -- To make type sigs not have qualified names+import Vivid.SynthDef.TypesafeArgs (AddParams)++import Vivid.UGens+import Vivid.OSC (addSecs)++import Control.Applicative+import Control.Monad+import Control.Monad.Random+import Data.ByteString (ByteString)+import Data.Function ((&))+import Data.Int+import Data.Monoid+import System.Random hiding (uniform)++import Control.Monad.IO.Class+import GHC.TypeLits++++bufToI :: KnownSymbol a => BufferId -> I a+bufToI (BufferId b) = toI b++bToI :: KnownSymbol a => BufferId -> I a+bToI = bufToI++b2i :: KnownSymbol a => BufferId -> I a+b2i = bufToI
Vivid/OSC/Bundles.hs view
@@ -1,7 +1,10 @@ -- | Vivid-specific OSC Bundle encoding -{-# LANGUAGE LambdaCase #-}-{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE+     LambdaCase+   , OverloadedStrings+   #-}+   -- , Safe  module Vivid.OSC.Bundles (      encodeOSCBundles
Vivid/SCServer.hs view
@@ -52,8 +52,8 @@     -- * Manual management of SC server connection -   , createSCServerConnection-   , closeSCServerConnection+   , createSCServerConnection'+   , closeSCServerConnection'    , SCConnectConfig(..)    , defaultConnectConfig @@ -67,14 +67,13 @@ import Vivid.OSC.Bundles (initTreeCommand) import qualified Vivid.SC.Server.Commands as SCCmd import Vivid.SC.Server.Types (Group(..), ParGroup(..))-import qualified Vivid.SC.Server.Commands as SCCmd  import Vivid.Actions.Class import Vivid.SCServer.Connection import Vivid.SCServer.State import Vivid.SCServer.Types -import qualified Data.ByteString.UTF8 as UTF8 (fromString)+-- import qualified Data.ByteString.UTF8 as UTF8 (fromString) import Data.Int (Int32) -- BBP hack: import Prelude@@ -153,13 +152,13 @@       SCCmd.b_write          bufId          fPath-         "wav"-         "float"+         "wav" -- TODO!+         "float" -- less important, but TODO          -- Num frames:          Nothing          -- Start frame:          0-         -- Whether to leave the file open (useful for diskOut)+         -- Whether to leave the file open (useful for diskOut):          (_wb_keepOpen args)          -- We make this synchronous because what if you send a          -- "/b_write" then a "/quit"?(!):
Vivid/SCServer/Connection.hs view
@@ -2,6 +2,7 @@      BangPatterns    , LambdaCase    , OverloadedStrings+   , ViewPatterns     , NoIncoherentInstances    , NoMonomorphismRestriction@@ -9,17 +10,33 @@    #-}  module Vivid.SCServer.Connection (-     createSCServerConnection+     createSCServerConnection'+    , defaultConnectConfig    , defaultMessageFunction    , ignoreMessagesFunction+    , SCConnectConfig(..)-   , closeSCServerConnection++   , closeSCServerConnection'+    , ConnProtocol(..)-   , getMailboxForSyncId-   , getSCServerSocket-   , waitForSync_io-   , waitForSync_io_noGC++   , getMailboxForSyncId'++   , getSCServerSocket'++   , waitForSync_io'+   , waitForSync_io_noGC'++   , sendMaybePad++   -- Exported at least for 'Vivid.GlobalState':+   , startMailbox'+   , connectToSCServer'++   -- for tests:+   , splitMessagesFromChunk    ) where  import Vivid.SC.Server.Commands as SCCmd@@ -29,26 +46,30 @@ import Vivid.SCServer.State  import Network.Socket (-     SocketType(Datagram {- , Stream -}), defaultProtocol, socket+     SocketType(Datagram , Stream), defaultProtocol, socket    , AddrInfo(..), getAddrInfo-   -- , AddrInfoFlag(..), defaultHints+   -- , AddrInfoFlag(..),+   , defaultHints    , Socket, HostName, ServiceName, connect, close -- , listen, bind    -- , bindSocket, accept+   , accept, listen                                                                  -- We put this everywhere we do socket actions for Windows compatibility:    , withSocketsDo    ) -import Network.Socket.ByteString (send, recv)+import Network.Socket.ByteString (sendAll, recv)  import Control.Concurrent (forkIO, ThreadId, killThread) import Control.Concurrent.MVar-import Control.Concurrent.STM -- (readTVar, modifyTVar', atomically, writeTVar, {- readTVarIO, -} swapTVar)+import Control.Concurrent.STM import Control.Monad (forever)+import Data.ByteString (ByteString)+import qualified Data.ByteString as BS import Data.Int (Int32)--- import Data.IORef import qualified Data.Map as Map import Data.Monoid+import Data.Serialize (encode, decode)  -- | __You usually don't need to call this function__ -- @@ -59,11 +80,11 @@ --   computation is done upfront --  --   The 'HostName' is the ip address or "localhost". The 'ServiceName' is the port-createSCServerConnection :: SCConnectConfig -> IO (Either String Socket)-createSCServerConnection connConfig = do-   let !_ = scServerState-   shouldMakeSock scServerState >>= \case-      True -> makeSock scServerState connConfig >>= \case+createSCServerConnection' :: SCServerState -> SCConnectConfig -> IO (Either String Socket)+createSCServerConnection' serverState connConfig = do+   let !_ = serverState+   shouldMakeSock serverState >>= \case+      True -> makeSock serverState connConfig >>= \case          Just s -> pure $ Right s          Nothing -> pure $ Left "Unable to create socket"       False ->@@ -81,24 +102,18 @@ --   Also if you want to change the params of your connection (e.g. to connect --   to a different server), you'll want to disconnect from the other --   connection first-closeSCServerConnection :: IO ()-closeSCServerConnection = do-   let !_ = scServerState+closeSCServerConnection' :: SCServerState -> IO ()+closeSCServerConnection' serverState = do+   let !_ = serverState    ish <- atomically $ do-      writeTVar (_scServerState_socketConnectStarted scServerState) False+      writeTVar (_scServerState_socketConnectStarted serverState) False {--      (,) <$> swapTVar (_scServerState_socket scServerState) Nothing-          <*> swapTVar (_scServerState_listener scServerState) Nothing+      (,) <$> swapTVar (_scServerState_socket serverState) Nothing+          <*> swapTVar (_scServerState_listener serverState) Nothing -}-      (,) <$> tryTakeTMVar (_scServerState_socket scServerState)-          <*> tryTakeTMVar (_scServerState_listener scServerState)+      (,) <$> tryTakeTMVar (_scServerState_socket serverState)+          <*> tryTakeTMVar (_scServerState_listener serverState) -{--   ish <- (,) <$> readIORef (_scServerState_socket scServerState)-              <*> readIORef (_scServerState_listener scServerState)-   writeIORef (_scServerState_socket scServerState) Nothing-   writeIORef (_scServerState_listener scServerState) Nothing--}    case ish of       (Just sock, Just listener) -> do          killThread listener@@ -107,12 +122,6 @@       _ -> error "well that's weird"  --data ConnProtocol-   = ConnProtocol_UDP-   -- ConnProtocol_TCP- deriving (Show, Read, Eq, Ord)- data SCConnectConfig    = SCConnectConfig {     _scConnectConfig_hostName :: HostName@@ -122,7 +131,9 @@      --   the same server, each client should have a separate clientId, which      --   keeps the nodeId separate. Sclang's default clientId is 0, and ours      --   is 1, so you can run both at the same time without config.+     --   This number must be between 0 and 31   , _scConnectConfig_connProtocol :: ConnProtocol+  , _scConnectConfig_password :: Maybe ByteString -- TODO: I don't like that e.g. a password could be provided with UDP, which doesn't use them   , _scConnectConfig_serverMessageFunction :: OSC -> IO ()   -- max # of synthdefs -- and clear em out   }@@ -136,71 +147,97 @@      _scConnectConfig_hostName = "127.0.0.1"    , _scConnectConfig_port = "57110"    , _scConnectConfig_clientId = 1-   , _scConnectConfig_connProtocol = ConnProtocol_UDP+   , _scConnectConfig_connProtocol = ConnProtocol_UDP -- ConnProtocol_TCP -- UDP -- TODO: not for release!+   , _scConnectConfig_password = Nothing    , _scConnectConfig_serverMessageFunction = defaultMessageFunction    }  -- Internal -- this is what gets called after we check a socket doesn't -- already exist:-connectToSCServer :: SCConnectConfig -> IO (Socket, ThreadId)-connectToSCServer scConnectConfig = withSocketsDo $ do-   let !_ = scServerState+connectToSCServer' :: SCServerState -> SCConnectConfig -> IO (Socket, ThreadId)+connectToSCServer' serverState scConnectConfig = withSocketsDo $ do+   let !_ = serverState    let hostName = _scConnectConfig_hostName scConnectConfig        port = _scConnectConfig_port scConnectConfig        connType = case _scConnectConfig_connProtocol scConnectConfig of           ConnProtocol_UDP -> Datagram---          ConnProtocol_TCP -> Stream-   (serverAddr:_) <- getAddrInfo Nothing {- (Just (defaultHints {addrFlags = [AI_PASSIVE]})) -} (Just hostName) (Just port)-   s <- socket (addrFamily serverAddr) connType defaultProtocol-   {--   if (connType == Stream)-      then do-         print 0-         bindSocket s (addrAddress serverAddr)-         print 1-         listen s 1-         -- _ <- accept s-         pure ()-   else connect s (addrAddress serverAddr)--}-   setClientId (_scConnectConfig_clientId scConnectConfig)+          ConnProtocol_TCP -> Stream+   (serverAddr:_) <- getAddrInfo (Just (defaultHints { addrSocketType = connType })) {- (Just (defaultHints {addrFlags = [AI_PASSIVE]})) -} (Just hostName) (Just port)+   s <- socket (addrFamily serverAddr) connType (addrProtocol serverAddr) -- defaultProtocol+   setServerClientId serverState (_scConnectConfig_clientId scConnectConfig)    connect s (addrAddress serverAddr)---   accept s -   atomically $ writeTVar (_scServerState_serverMessageFunction scServerState) $-      _scConnectConfig_serverMessageFunction scConnectConfig-   listener <- forkIO $ startMailbox s+   atomically $ do+      writeTVar (_scServerState_serverMessageFunction serverState) $+         _scConnectConfig_serverMessageFunction scConnectConfig+      writeTVar (_scServerState_connProtocol serverState) $+         _scConnectConfig_connProtocol scConnectConfig+++   case _scConnectConfig_password scConnectConfig of+      Nothing -> pure ()+      -- This must be the very first message sent to the server:+      Just password -> sendAll {- MaybePad  (_scConnectConfig_connProtocol scConnectConfig) -} s $ password++   listener <- forkIO $ startMailbox' serverState s+    let firstSyncID = toEnum $ numberOfSyncIdsToDrop - 2-   _ <- send s $ encodeOSCBundle $ OSCBundle (Timestamp 0) [+   _ <- sendMaybePad (_scConnectConfig_connProtocol scConnectConfig) s $+      encodeOSCBundle $ OSCBundle (Timestamp 0) [         Right $ SCCmd.dumpOSC DumpOSC_Parsed       , Right $ initTreeCommand       , Right $ SCCmd.sync (SyncId firstSyncID)       ]-   waitForSync_io (SyncId firstSyncID)++   waitForSync_io' serverState (SyncId firstSyncID)+    pure (s, listener) -waitForSync_io :: SyncId -> IO ()-waitForSync_io syncId = do-   _ <- readMVar =<< getMailboxForSyncId syncId+-- ALWAYS use this instead of 'send':+sendMaybePad :: ConnProtocol -> Socket -> ByteString -> IO ()+sendMaybePad connProtocol socket msg_noPad =+   withSocketsDo $ sendAll socket msg -- TODO: send vs sendAll? Makes a difference?+ where+   msg :: ByteString+   msg = case connProtocol of+      ConnProtocol_UDP -> msg_noPad+      ConnProtocol_TCP -> (encode (toEnum (BS.length msg_noPad) :: Int32))<>msg_noPad++waitForSync_io' :: SCServerState -> SyncId -> IO ()+waitForSync_io' serverState syncId = do+   _ <- readMVar =<< getMailboxForSyncId' serverState syncId    -- We garbage-collect these so the Map stays small -- but it means you can only wait    -- for a sync from one place:-   atomically $ modifyTVar' (_scServerState_syncIdMailboxes scServerState) $+   atomically $ modifyTVar' (_scServerState_syncIdMailboxes serverState) $       Map.delete syncId -waitForSync_io_noGC :: SyncId -> IO ()-waitForSync_io_noGC syncId = do-   _ <- readMVar =<< getMailboxForSyncId syncId+waitForSync_io_noGC' :: SCServerState -> SyncId -> IO ()+waitForSync_io_noGC' serverState syncId = do+   _ <- readMVar =<< getMailboxForSyncId' serverState syncId    pure ()  -- TODO: what's "mailbox" here? Is it like an Erlang mailbox, to receive and -- dispatch all messages?-startMailbox :: Socket -> IO ()-startMailbox s = do-   let !_ = scServerState-   forever $ recv {- From -} s 65536 >>= \(msg{- , _ -}) ->+startMailbox' :: SCServerState -> Socket -> IO ()+startMailbox' serverState s = do+   let !_ = serverState+   connProtocol <- readTVarIO $ _scServerState_connProtocol serverState :: IO ConnProtocol -- note we only read this once at the beginning. If this can change throughout program run, update this code+   forever $ recv {- From -} s 65536 >>= \(msg_maybePad {- , _ -}) -> do+      case connProtocol of+         ConnProtocol_UDP ->+            handleMsg msg_maybePad+         ConnProtocol_TCP -> do+            case splitMessagesFromChunk msg_maybePad of -- From the 'network' docs: "For TCP sockets, a zero length return value means the peer has closed its half side of the connection."+               Right [] -> errorWithoutStackTrace "Connection to the SC server lost. Probably the server has quit or the network is down. You will need to reconnect."+               Left err -> putStrLn err+               Right msgs ->+                  mapM_ handleMsg msgs+ where+   handleMsg :: ByteString -> IO ()+   handleMsg msg = do       case decodeOSC msg of          Right (OSC "/synced" [OSC_I theSyncId]) -> do-            syncBox <- getMailboxForSyncId (SyncId theSyncId)+            syncBox <- getMailboxForSyncId' serverState (SyncId theSyncId)             tryPutMVar syncBox () >>= \case                True -> pure ()                False ->@@ -209,10 +246,30 @@                      ++ show theSyncId          Right x -> do             otherMessageFunction <- readTVarIO $-               _scServerState_serverMessageFunction scServerState+               _scServerState_serverMessageFunction serverState             otherMessageFunction x-         Left e -> putStrLn $ "ERROR DECODING OSC: " ++ show (msg, e)+         Left e -> do+            putStrLn $ "ERROR DECODING OSC: " ++ show (msg, e) +-- There can be more than one message that we recieve as one binary blob:+splitMessagesFromChunk :: ByteString -> Either String [ByteString]+splitMessagesFromChunk b =+   case BS.splitAt 4 b of+      ("", "") -> Right []+      (sizeBS, rest) ->+         case decode sizeBS :: Either String Int32 of+            Left e -> Left $ "ERROR DECODING OSC PAD: "++show b+            Right (fromEnum -> size) ->+               let (thisChunk, nextBS) = BS.splitAt size rest+               in case BS.length thisChunk == size of+                     False -> Left $ "INCORRECT SIZE: "++show b+                     True ->+                        case splitMessagesFromChunk nextBS of+                           Left e -> Left e+                           Right allRest -> Right (thisChunk : allRest)+++ -- | Print all messages other than \"/done\"s defaultMessageFunction :: OSC -> IO () defaultMessageFunction = \case@@ -233,20 +290,18 @@ -- This is a nice example of when STM can be really helpful - -- It's impossible! (right?) to have 2 threads create mailboxes and have em overwrite each -- other -- so we can make a guarantee about recieving a sync that you register for-getMailboxForSyncId :: SyncId -> IO (MVar ())-getMailboxForSyncId syncId = do-   mvarThatIMightWannaUse <- newEmptyMVar-   atomically $ do-      allMailboxes <- readTVar (_scServerState_syncIdMailboxes scServerState)+getMailboxForSyncId' :: SCServerState -> SyncId -> IO (MVar ())+getMailboxForSyncId' serverState syncId = do+   mvarThatIMightWannaUse <- newEmptyMVar -- TODO: make this a TMVar so it doesn't have to sit outside like this?+   m <- atomically $ do+      allMailboxes <- readTVar (_scServerState_syncIdMailboxes serverState)       case Map.lookup syncId allMailboxes of          Just syncBox -> pure syncBox          Nothing -> do-            writeTVar (_scServerState_syncIdMailboxes scServerState)+            writeTVar (_scServerState_syncIdMailboxes serverState)               (Map.insert syncId mvarThatIMightWannaUse allMailboxes)             pure mvarThatIMightWannaUse--getSCServerSocket :: IO Socket-getSCServerSocket = getSCServerSocket' scServerState+   pure m  getSCServerSocket' :: SCServerState -> IO Socket getSCServerSocket' scServerState' = do@@ -270,7 +325,7 @@  makeSock :: SCServerState -> SCConnectConfig -> IO (Maybe Socket) makeSock serverState connConfig = do-   (sock, listener) <- connectToSCServer connConfig+   (sock, listener) <- connectToSCServer' serverState connConfig    atomically $ (do       -- writeTVar (_scServerState_socket serverState) $ Just sock       -- writeTVar (_scServerState_listener serverState) $ Just listener
Vivid/SCServer/State.hs view
@@ -1,7 +1,9 @@-{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE KindSignatures #-}-{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE+     BangPatterns+   , DataKinds+   , KindSignatures+   , LambdaCase+   #-}  {-# LANGUAGE NoIncoherentInstances #-} {-# LANGUAGE NoMonomorphismRestriction #-}@@ -12,14 +14,21 @@    , NodeId(..)    , SyncId(..) -   , scServerState    , SCServerState(..) -   , setClientId-   , setMaxBufferIds+   , ConnProtocol(..) -   , getNextAvailable+   , setServerClientId++   , setServerMaxBufferIds+    , numberOfSyncIdsToDrop++   , makeEmptySCServerState++   -- We might not need to export these (or the global equivalents) at all:+   , getNextAvailable'+   , getNextAvailables'    ) where  import Vivid.OSC (OSC)@@ -41,19 +50,6 @@ import Data.Set (Set) import Prelude --- We use this only for "the unsafePerformIO hack"--- (https://wiki.haskell.org/Top_level_mutable_state) so that functions can--- refer to the state without being passed the state explicitly. This should--- still be safe:-import System.IO.Unsafe (unsafePerformIO)--{-# NOINLINE scServerState #-}-scServerState :: SCServerState--- Currently you can only be connected to one SC server at a time. Future---   versions plan to remove this.--- See the above note about this use of unsafePerformIO:-scServerState = unsafePerformIO makeEmptySCServerState- data SCServerState    = SCServerState    -- We use 'IORef Maybe's instead of MVars so we can use weak pointer@@ -69,17 +65,26 @@   , _scServerState_syncIdMailboxes :: !(TVar (Map SyncId (MVar ())))   , _scServerState_serverMessageFunction :: !(TVar (OSC -> IO ()))   , _scServerState_definedSDs :: !(TVar (Set (SDName, Int))) -- Int is the hash+  , _scServerState_connProtocol :: TVar ConnProtocol -- This doesn't change after boot, but we could e.g. disconnect and reconnect after boot   } -setClientId :: Int32 -> IO ()-setClientId clientId = do+data ConnProtocol+   = ConnProtocol_UDP+   | ConnProtocol_TCP+ deriving (Show, Read, Eq, Ord)++setServerClientId :: SCServerState -> Int32 -> IO ()+setServerClientId serverState clientId = do    when (clientId < 0 || clientId > 31) $       error "client id must be betw 0 and 31"-   atomically $ writeTVar (_scServerState_availableNodeIds scServerState) $+   atomically $ writeTVar (_scServerState_availableNodeIds serverState) $       -- The client id is the first 5 bits of a positive int:       -- Note the incrementing gets weird once we hit the (.&.) -- should       -- fix if anyone plans to use more than 33 million nodes-      (flip map) [1000..] $ \nodeNum -> NodeId $+      map f [1000..]+ where+   f :: Int32 -> NodeId+   f nodeNum = NodeId $          ((clientId `shiftL` ((finiteBitSize nodeNum-5)-1)) .|.) $             ((maxBound `shiftR` 5) .&. nodeNum) @@ -103,6 +108,7 @@    syncMailboxes <- newTVarIO $ Map.empty    serverMessageFunction <- newTVarIO $ \_ -> return ()    definedSDs <- newTVarIO $ Set.empty+   connProtocolVar <- newTVarIO ConnProtocol_UDP     return $ SCServerState           { _scServerState_socketConnectStarted = sockConnectStarted@@ -115,6 +121,7 @@           , _scServerState_syncIdMailboxes = syncMailboxes           , _scServerState_serverMessageFunction = serverMessageFunction           , _scServerState_definedSDs = definedSDs+          , _scServerState_connProtocol = connProtocolVar           }  -- | If you've started the SC server with a non-default number of buffer ids,@@ -122,21 +129,23 @@ --  --   Note that the buffer ids start at 512, to not clash with any that --   another client (e.g. sclang) has allocated-setMaxBufferIds :: Int32 -> IO ()-setMaxBufferIds newMax = atomically $-   writeTVar (_scServerState_maxBufIds scServerState) newMax+setServerMaxBufferIds :: SCServerState -> Int32 -> IO ()+setServerMaxBufferIds serverState newMax =+   atomically $+      writeTVar (_scServerState_maxBufIds serverState) newMax -getNextAvailable :: (SCServerState -> TVar [a]) -> IO a-getNextAvailable getter =-   getNextAvailables 1 getter >>= \case+getNextAvailable' :: SCServerState -> (SCServerState -> TVar [a]) -> IO a+getNextAvailable' serverState getter =+   getNextAvailables' serverState 1 getter >>= \case       [x] -> return x       _ -> error "i don't even - 938" -getNextAvailables :: Int -> (SCServerState -> TVar [a]) -> IO [a]-getNextAvailables numToGet getter = do-   let !_ = scServerState+getNextAvailables' :: SCServerState -> Int -> (SCServerState -> TVar [a]) -> IO [a]+getNextAvailables' serverState numToGet getter = do+   let !_ = serverState    atomically $ do-      let avail = getter scServerState+      let avail = getter serverState       (ns, rest) <- splitAt numToGet <$> readTVar avail       writeTVar avail rest       return ns+
Vivid/SCServer/Types.hs view
@@ -1,5 +1,7 @@-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE+     DataKinds+   , KindSignatures+   #-}  {-# LANGUAGE NoIncoherentInstances #-} {-# LANGUAGE NoMonomorphismRestriction #-}@@ -19,7 +21,6 @@    , IsGroup    ) where -import Data.Int import GHC.TypeLits import Vivid.SC.Server.Types import Vivid.SynthDef.TypesafeArgs
Vivid/SynthDef.hs view
@@ -37,12 +37,14 @@  {-# LANGUAGE NoRebindableSyntax #-} -{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE LambdaCase #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TypeFamilies, NoMonoLocalBinds #-}-{-# LANGUAGE ViewPatterns #-}+{-# LANGUAGE+     BangPatterns+   , DataKinds+   , LambdaCase+   , OverloadedStrings+   , TypeFamilies, NoMonoLocalBinds+   , ViewPatterns+   #-}  {-# LANGUAGE NoIncoherentInstances #-} {-# LANGUAGE NoMonomorphismRestriction #-}@@ -57,6 +59,7 @@   , addUGen   , addMonoUGen   , addPolyUGen+  , addOrIncrementMaxLocalBufs   , ToSig(..)   , Signal(..)   , encodeSD@@ -105,7 +108,6 @@ import Vivid.SynthDef.FromUA (SDBody)  -- import Control.Applicative-import Control.Arrow (first{-, second-}) import Control.Monad.State (get, put, modify, execState) import Data.ByteString (ByteString) import qualified Data.ByteString.UTF8 as UTF8@@ -294,6 +296,28 @@       }    return $ map (UGOut anId) [0.. toEnum (_ugenNumOuts ugen - 1)] +-- In all (as of this writing) other cases, UGens are 'write only': you can+--   just add them, not edit or remove them. However! SC has a special case+--   where if you create a LocalBuf, you need to have previously a+--   'MaxLocalBufs' which says how many LocalBufs there are in the whole graph.+--   So for that, we update our 'MaxLocalBufs'+addOrIncrementMaxLocalBufs :: SDBody' args Signal+addOrIncrementMaxLocalBufs = do+   (ids, synthDef, argList) <- get+   case Map.toList $ Map.filter isMLB $ _sdUGens synthDef of+      [] -> addMonoUGen $ UGen (UGName_S "MaxLocalBufs") IR [Constant 1] 1+      [(ugIndex,     UGen (UGName_S "MaxLocalBufs") IR [Constant numPreviously]      1)] -> do+         let newUG = UGen (UGName_S "MaxLocalBufs") IR [Constant (numPreviously + 1)] 1+             newSD = synthDef { _sdUGens = Map.insert ugIndex newUG $ _sdUGens synthDef }+         put $ (ids, newSD, argList)+         pure $ UGOut ugIndex 0+      [e] -> error $ "Incorrectly constructed MLB?: "++show e+      es -> error $ "Multiple MLB?: "++show es+ where+   isMLB = \case+      UGen (UGName_S "MaxLocalBufs") _ _ _ -> True+      _ -> False+ -- | Define a Synth Definition sd :: VarList argList => argList -> SDBody' (InnerVars argList) [Signal] -> SynthDef (InnerVars argList) sd params theState =@@ -306,11 +330,15 @@  makeSynthDef :: VarList argList => SDName -> argList -> SDBody' (InnerVars argList) [Signal] -> SynthDef (InnerVars argList) makeSynthDef name params theState =-   let theSD = SynthDef name (map (first UTF8.fromString) paramList) Map.empty-       (paramList, argSet) = makeTypedVarList params-   in (\(_,b,_)->b) $ execState theState $-         ({- id supply: -} [0 :: Int ..], theSD, argSet)+   b+ where+   paramList :: [(String, Float)]+   (paramList, argSet) = makeTypedVarList params +   sdBeforeBody = SynthDef name [ (UTF8.fromString k, v) | (k, v) <- paramList ] Map.empty+   (_,b,_) = execState theState $+      ({- id supply: -} [0 :: Int ..], sdBeforeBody, argSet)+ -- | Set the calculation rate of a UGen --  --   e.g.@@ -341,15 +369,16 @@    return i'  getCalcRate :: Signal -> SDBody' args CalculationRate-getCalcRate (Constant _) = return IR-getCalcRate (Param _) = return KR-getCalcRate (UGOut theUG _) = do-   -- Note: this assumes updates to the ugen graph are only appends-   -- (so don't break that invariant if you build your own graph by hand!):-   (_, ugenGraph, _) <- get-   case Map.lookup theUG (_sdUGens ugenGraph) of-      Just ug -> return $ _ugenCalculationRate ug-      Nothing -> error "that output isn't in the graph!"+getCalcRate = \case+   Constant _ -> pure IR+   Param _ -> pure KR+   UGOut theUG _ -> do+      -- Note: this assumes updates to the ugen graph are only appends+      -- (so don't break that invariant if you build your own graph by hand!):+      (_, ugenGraph, _) <- get+      case Map.lookup theUG (_sdUGens ugenGraph) of+         Just ug -> return $ _ugenCalculationRate ug+         Nothing -> error "that output isn't in the graph!"   -- | Like 'Vivid.SCServer.shrinkSynthArgs' but for 'SynthDef's
Vivid/SynthDef/ToSig.hs view
@@ -26,8 +26,11 @@ import Vivid.SynthDef.Types  import qualified Data.ByteString.UTF8 as UTF8+import Data.Int (Int8, Int16, Int32, Int64)+import Data.Word (Word8, Word16, Word32, Word64) -- import Data.Proxy import GHC.TypeLits+import Numeric.Natural (Natural)  class ToSig s (args :: [Symbol]) where    toSig :: s -> SDBody' args Signal@@ -41,17 +44,28 @@  #if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 801 -instance ToSig Integer args where-   toSig = pure . Constant . realToFrac+realSig :: (Real n, Applicative f) => n -> f Signal+realSig = pure . Constant . realToFrac -instance ToSig Int args where-   toSig = pure . Constant . realToFrac+instance ToSig Double       args where toSig = realSig+instance ToSig Float        args where toSig = realSig -instance ToSig Double args where-   toSig = pure . Constant . realToFrac+instance ToSig Rational     args where toSig = realSig -instance ToSig Float args where-   toSig = pure . Constant . realToFrac+instance ToSig Integer      args where toSig = realSig+instance ToSig Natural      args where toSig = realSig++instance ToSig Int          args where toSig = realSig+instance ToSig Int8         args where toSig = realSig+instance ToSig Int16        args where toSig = realSig+instance ToSig Int32        args where toSig = realSig+instance ToSig Int64        args where toSig = realSig++instance ToSig Word         args where toSig = realSig+instance ToSig Word8        args where toSig = realSig+instance ToSig Word16       args where toSig = realSig+instance ToSig Word32       args where toSig = realSig+instance ToSig Word64       args where toSig = realSig  #else 
Vivid/SynthDef/Types.hs view
@@ -3,11 +3,13 @@ {-# OPTIONS_HADDOCK show-extensions #-} -- {-# LANGUAGE DeriveGeneric #-} -{-# LANGUAGE DataKinds #-}+{-# LANGUAGE+     DataKinds+   , KindSignatures+   , OverloadedStrings+   , TypeFamilies, NoMonoLocalBinds+   #-} -- {-# LANGUAGE GADTs, NoMonoLocalBinds #-}-{-# LANGUAGE KindSignatures #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TypeFamilies, NoMonoLocalBinds #-}  {-# LANGUAGE NoIncoherentInstances #-} {-# LANGUAGE NoMonomorphismRestriction #-}
Vivid/UGens.hs view
@@ -29,7 +29,7 @@ {-# LANGUAGE NoUndecidableInstances #-} {-# LANGUAGE NoIncoherentInstances #-} -{-# LANGUAGE ExistentialQuantification #-}+-- {-# LANGUAGE ExistentialQuantification #-}  module Vivid.UGens (      module Vivid.UGens.Args
Vivid/UGens/Analysis.hs view
@@ -72,6 +72,8 @@  --- detectSilence :: --- detectSilence =++ --- loudness :: --- loudness = --- peak ::
Vivid/UGens/Args.hs view
@@ -1,21 +1,23 @@ -- | UGen argument labels -- ---   These are named the same as their SC counterparts, usually.+--   These are usually named the same as their sclang counterparts.  {-# OPTIONS_HADDOCK show-extensions #-}  {-# LANGUAGE NoRebindableSyntax #-} -{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE ExistentialQuantification #-}-{-# LANGUAGE NoMonomorphismRestriction #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE KindSignatures #-}-{-# LANGUAGE PartialTypeSignatures #-}-{-# LANGUAGE TypeFamilies, NoMonoLocalBinds #-}-{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE+     ConstraintKinds+   , DataKinds+   , ExistentialQuantification+   , NoMonomorphismRestriction+   , FlexibleContexts+   , FlexibleInstances+   , KindSignatures+   , PartialTypeSignatures+   , TypeFamilies, NoMonoLocalBinds+   , TypeOperators+   #-}   {-# LANGUAGE NoIncoherentInstances #-}@@ -181,6 +183,13 @@ decayTime_ :: ToSig s as => s -> UA "decaySecs" as decayTime_ = decaySecs_ +decayScale_ :: ToSig s as => s -> UA "decayScale" as+decayScale_ = UA . toSig++-- | SC compatibility+decayscale_ :: ToSig s as => s -> UA "decayScale" as+decayscale_ = decayScale_+ -- | Alias of 'decaySecs_' for SC compatibility decaytime_ :: ToSig s as => s -> UA "decaySecs" as decaytime_ = decaySecs_@@ -286,6 +295,21 @@ freq_ :: ToSig s as => s -> UA "freq" as freq_  = UA . toSig +freqOffset_ :: ToSig s as => s -> UA "freqOffset" as+freqOffset_ = UA . toSig++-- | SC compatibility:+freqoffset_ :: ToSig s as => s -> UA "freqOffset" as+freqoffset_ = freqOffset_+++freqScale_ :: ToSig s as => s -> UA "freqScale" as+freqScale_ = UA . toSig++-- | SC compatibility:+freqscale_ :: ToSig s as => s -> UA "freqScale" as+freqscale_ = freqScale_+ friction_ :: ToSig s as => s -> UA "friction" as friction_ = UA . toSig @@ -647,11 +671,11 @@    , SDBodyArgs optional ~ SDBodyArgs userSupplied    , SDBodyArgs optional ~ args    ) => (UGen -> SDBody' args x) -> Int -> String -> CalculationRate -> Vs tags -> optional -> (userSupplied -> SDBody' args x)-makeMakeUGen addUGenF numOuts sdName calcRate tagList defaultArgs = \userSupplied -> do+makeMakeUGen addUGenF numOuts ugenName calcRate tagList defaultArgs = \userSupplied -> do    theArgList <- Map.fromList <$> fromUAWithDefaults (DefaultArgs defaultArgs) (OverwritingArgs userSupplied)    let signals =-          map (\k -> Map.findWithDefault (error $ "that's weird (likely a ugen with a typo in 'Vs'): "++sdName++":"++k) k theArgList) $ getSymbolVals tagList-   addUGenF $ UGen (UGName_S (UTF8.fromString sdName)) calcRate (signals :: [Signal]) numOuts+          map (\k -> Map.findWithDefault (error $ "that's weird (likely a ugen with a typo in 'Vs'): "++ugenName++":"++k) k theArgList) $ getSymbolVals tagList+   addUGenF $ UGen (UGName_S (UTF8.fromString ugenName)) calcRate (signals :: [Signal]) numOuts  makeMonoUGen, makeUGen :: (      GetSymbolVals (Vs tags)
Vivid/UGens/Buffer.hs view
@@ -1,13 +1,15 @@-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE ExtendedDefaultRules #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE LambdaCase #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TypeFamilies, NoMonoLocalBinds #-}+{-# LANGUAGE+     DataKinds+   , ExtendedDefaultRules+   , FlexibleContexts+   , LambdaCase+   , OverloadedStrings+   , TypeFamilies, NoMonoLocalBinds -{-# LANGUAGE NoIncoherentInstances #-}-{-# LANGUAGE NoMonomorphismRestriction #-}-{-# LANGUAGE NoUndecidableInstances #-}+   , NoIncoherentInstances+   , NoMonomorphismRestriction+   , NoUndecidableInstances+   #-}  module Vivid.UGens.Buffer ( @@ -43,7 +45,10 @@ ---   , multiTap    , phasor    , playBuf+   , playBufPoly+    , recordBuf+   , recordBufPoly ---   , scopeOut ---   , shaper      -- In Vivid.UGens.Generators.Granular@@ -70,13 +75,14 @@ --   and 'frames_' for \"Vivid.UGens.Args.numFrames\" localBuf :: Args '["numChans","numFrames"] '[] a => a -> SDBody a Signal localBuf args = do-   mlb <- addUGen $ UGen (UGName_S "MaxLocalBufs") IR [Constant 1] 1+   mlb <- addOrIncrementMaxLocalBufs    numChannels' <- uaArgVal args (Proxy::Proxy "numChans")    numFrames' <- uaArgVal args (Proxy::Proxy "numFrames")    -- Another example where the args in sclang and scsynth are in different orders:    addUGen $ UGen (UGName_S "LocalBuf") IR [numChannels', numFrames', mlb] 1  +{-# DEPRECATED playBuf "use playBufPoly instead (and use bufRateScale and set doneAction)" #-} -- | Unlike in SC, \"doneAction\\" defaults to 2 --  --   Also, the default rate is the 'bufRateScale' of the buffer@@ -93,6 +99,12 @@           -- todo : put bufratescale on all of em if we decide to keep this behavior    defaultRate = bufRateScale $ uaArgVal args (V::V "buf") +playBufPoly :: (Args '["buf"] '["rate","trigger","startPos","loop","doneAction"] a) => Int -> a -> SDBody a [Signal]+playBufPoly numChans args = ($ args) $ makePolyUGen numChans+   "PlayBuf" AR+   (Vs::Vs '["buf","rate","trigger","startPos","loop","doneAction"])+   (rate_ (1::Float), trigger_ ((1)::Float), startPos_ ((0)::Float)+   ,loop_ ((0)::Float), doneAction_ (0::Float)) -- NOTE doneAction is back to 0...! Good idea? (TODO)  -- | Unlike in SC, "doneAction" defaults to 2 and "loop" defaults to 0 recordBuf :: (Args '["buf","in"] '["offset","recLevel","preLevel","run","loop","trigger","doneAction"] a) => a -> SDBody a Signal@@ -102,6 +114,16 @@    -- this is another example of different order:    (offset_ ((0)::Float), recLevel_ ((1)::Float), preLevel_ ((0)::Float), run_ ((1)::Float), loop_ ((0)::Float), trigger_ ((1)::Float), doneAction_ ((2)::Float)) +-- | Unlike in SC, "doneAction" defaults to 2 and "loop" defaults to 0+recordBufPoly :: (Args '["buf","in"] '["offset","recLevel","preLevel","run","loop","trigger","doneAction"] a) => Int -> a -> SDBody a [Signal]+recordBufPoly numChans = makePolyUGen numChans+   "RecordBuf" AR+   (Vs::Vs '["buf","offset","recLevel","preLevel","run","loop","trigger","doneAction","in"])+   -- this is another example of different order:+   (offset_ ((0)::Float), recLevel_ ((1)::Float), preLevel_ ((0)::Float), run_ ((1)::Float), loop_ ((0)::Float), trigger_ ((1)::Float), doneAction_ ((2)::Float))+++ -- | Defaults to 'KR'. Can be 'IR' too but be careful that the buffer doesn't change if so! bufChannels :: (Args '["buf"] '[] a) => a -> SDBody a Signal bufChannels = makeUGen@@ -122,7 +144,7 @@ --  --   Note you don't need to use "buf_" when you use this bufFrames :: ToSig s as => s -> SDBody' as Signal-bufFrames = (flip (.)) buf_ $ makeUGen+bufFrames = (. buf_) $ makeUGen    "BufFrames" KR    (Vs::Vs '["buf"])    NoDefaults@@ -144,7 +166,7 @@ --  --   Note you don't need to use "buf_" when you use this bufSampleRate :: ToSig s as => s -> SDBody' as Signal-bufSampleRate = (flip (.)) buf_ $ makeUGen+bufSampleRate = (. buf_) $ makeUGen    "BufSampleRate" KR    (Vs::Vs '["buf"])    NoDefaults@@ -155,7 +177,7 @@ --  --   Note you don't need to use "buf_" when you use this bufSamples :: ToSig s as => s -> SDBody' as Signal-bufSamples = (flip (.)) buf_ $ makeUGen+bufSamples = (. buf_) $ makeUGen    "BufSamples" KR    (Vs::Vs '["buf"])    NoDefaults
Vivid/UGens/Envelopes.hs view
@@ -174,15 +174,17 @@ -- | Percussive hit --  --   'doneAction' is currently 2 but may either be 0 or 2 in future versions-percGen :: (Args '[] '["attackSecs", "releaseSecs", "level", "curve", "doneAction"] a) => a -> SDBody a Signal+percGen :: (Args '[] '["attackSecs", "releaseSecs", "level", "curve", "doneAction", "gate", "fadeSecs"] a) => a -> SDBody a Signal percGen userArgs = do    level <- uaArgWDef_onlyConst (1::Float) userArgs (V::V "level")    attackTime <- uaArgWDef_onlyConst (0.01::Float) userArgs (V::V "attackSecs")    releaseTime <- uaArgWDef_onlyConst (1::Float) userArgs (V::V "releaseSecs")    curve <- uaArgWDef_onlyConst (-4::Float) userArgs (V::V "curve")    doneAction <- fromEnum <$> uaArgWDef_onlyConst (2::Float) userArgs (V::V "doneAction")+   gate <- uaArgValWDefault 1 userArgs (V::V "gate")+   timeScale <- uaArgValWDefault 1 userArgs (V::V "fadeSecs") -   envGen (env 0 [(level, attackTime), (0, releaseTime)] (Curve_Curve curve)) (DoneAction_AsNum doneAction)+   envGen_wGate gate timeScale (env 0 [(level, attackTime), (0, releaseTime)] (Curve_Curve curve)) (DoneAction_AsNum doneAction)  where    uaArgWDef_onlyConst defaultVal args argName =       uaArgValWDefault defaultVal args argName >>= \case
Vivid/UGens/FFT.hs view
@@ -33,7 +33,7 @@     -- * FFT functions ----   , pv_add+   , pv_add    , pv_binScramble    , pv_binShift ---   , pv_binWipe@@ -41,10 +41,10 @@ ---   , pv_chainUGen    , pv_conformalMap    , pv_conj----   , pv_copy----   , pv_copyPhase+   , pv_copy+   , pv_copyPhase    , pv_diffuser----   , pv_div+   , pv_div ---   , pv_hainsworthFoote ---   , pv_jensenAndersen    , pv_localMax@@ -58,9 +58,9 @@    , pv_magShift    , pv_magSmear    , pv_magSquared----   , pv_max----   , pv_min----   , pv_mul+   , pv_max+   , pv_min+   , pv_mul    , pv_phaseShift    , pv_phaseShift270    , pv_phaseShift90@@ -70,6 +70,8 @@ ---   , pv_rectComb2    ) where +import Data.ByteString (ByteString)+ import Vivid.SC.SynthDef.Types (CalculationRate(..)) import Vivid.SynthDef import Vivid.UGens.Args@@ -120,9 +122,9 @@ --- unpackFFT = -- frombin: 0 ---- pv_add :: (ToSig bufA as, ToSig bufB as) => bufA -> bufB -> SDBody' as Signal---- pv_add bufA bufB =-+pv_add :: (ToSig bufA as, ToSig bufB as) => bufA -> bufB -> SDBody' as Signal+pv_add =+   twoArgUGen "PV_Add"  pv_binScramble :: (Args '["buf"] '["wipe", "width", "trigger"] a) => a -> SDBody a Signal pv_binScramble = makeUGen@@ -160,20 +162,31 @@    (Vs::Vs '["buf"])    NoDefaults ---- pv_copy :: (ToSig bufA as, ToSig bufB as) => SDBody' as Signal---- pv_copy bufA bufB =+pv_copy :: (ToSig bufA as, ToSig bufB as) => bufA -> bufB -> SDBody' as Signal+pv_copy =+   twoArgUGen "PV_Copy" ---- pv_copyPhase :: (ToSig bufA as, ToSig bufB as) => SDBody' as Signal---- pv_copyPhase bufA bufB =+pv_copyPhase :: (ToSig bufA as, ToSig bufB as) => bufA -> bufB -> SDBody' as Signal+pv_copyPhase =+   twoArgUGen "PV_CopyPhase" ++twoArgUGen :: (ToSig s0 as, ToSig s1 as) => ByteString -> s0 -> s1 -> SDBody' as Signal+twoArgUGen ugenName s0 s1 = do+   s0' <- toSig s0+   s1' <-  toSig s1+   addMonoUGen $ UGen (UGName_S ugenName) KR [s0', s1'] 1++ pv_diffuser :: (Args '["buf"] '["trigger"] a) => a -> SDBody a Signal pv_diffuser = makeUGen    "PV_Diffuser" KR    (Vs::Vs '["buf", "trigger"])    (trig_ (0::Float)) ---- pv_div :: (ToSig bufA as, ToSig bufB as) => bufA -> bufB -> SDBody' as Signal---- pv_div bufA bufB =+pv_div :: (ToSig bufA as, ToSig bufB as) => bufA -> bufB -> SDBody' as Signal+pv_div =+   twoArgUGen "PV_Div"  --- pv_hainsworthFoote :: --- pv_hainsworthFoote =@@ -241,13 +254,17 @@    (Vs::Vs '["buf"])    NoDefaults ---- pv_max :: (ToSig bufA as, ToSig bufB as) => bufA -> bufB -> SDBody' as Signal---- pv_max bufA bufB = do-   ------ pv_min :: (ToSig bufA as, ToSig bufB as) => bufA -> bufB -> SDBody' as Signal---- pv_min bufA bufB =---- pv_mul :: (ToSig bufA as, ToSig bufB as) => bufA -> bufB -> SDBody' as Signal---- pv_mul bufA bufB =+pv_max :: (ToSig bufA as, ToSig bufB as) => bufA -> bufB -> SDBody' as Signal+pv_max =+   twoArgUGen "PV_Max"++pv_min :: (ToSig bufA as, ToSig bufB as) => bufA -> bufB -> SDBody' as Signal+pv_min =+   twoArgUGen "PV_Min"++pv_mul :: (ToSig bufA as, ToSig bufB as) => bufA -> bufB -> SDBody' as Signal+pv_mul =+   twoArgUGen "PV_Mul"  pv_phaseShift :: (Args '["buf", "shift"] '["integrate"] a) => a -> SDBody a Signal pv_phaseShift = makeUGen
Vivid/UGens/Filters/Linear.hs view
@@ -1,5 +1,8 @@-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE+     DataKinds+   , FlexibleContexts+   , OverloadedStrings+   #-}  {-# LANGUAGE NoIncoherentInstances #-} {-# LANGUAGE NoMonomorphismRestriction #-}@@ -50,6 +53,7 @@ import Vivid.UGens.Args import Vivid.SynthDef.FromUA +import Control.Monad (forM) import qualified Data.ByteString.UTF8 as UTF8 import Data.Monoid import Data.Proxy@@ -151,18 +155,24 @@ --   Each tuple in the list argument is a triple of frequency, amplitude, and ring time --  --   Can only run in 'AR'-klank :: Args '["in"] '[] a => a -> [(Float, Float, Float)] -> SDBody a Signal+klank :: (Args '["in"] '["freqScale", "freqOffset", "decayScale"] a, ToSig freq (SDBodyArgs a), ToSig amp (SDBodyArgs a), ToSig ring (SDBodyArgs a)) => a -> [(freq, amp, ring)] -> SDBody a Signal klank args resonators = do    in' <- uaArgVal args (Proxy::Proxy "in")-   addMonoUGen $ UGen (UGName_S (UTF8.fromString "Klank")) AR (outs in') 1- where-   outs inThing = [-        inThing-         -- These may be added as parameters in the future:-      , Constant 1 -- freqscale-      , Constant 0 -- freqoffset-      , Constant 1 -- decayscale-      ] <> concat [ map Constant [a,b,c] | (a,b,c) <- resonators ]+   freqscale <-  uaArgValWDefault 1 args (Proxy::Proxy "freqScale")+   freqoffset <- uaArgValWDefault 0 args (Proxy::Proxy "freqOffset")+   decayscale <- uaArgValWDefault 1 args (Proxy::Proxy "decayScale")+   resonators' <- forM resonators $ \(freq, amp, ring) -> do+      f <- toSig freq+      a <- toSig amp+      r <- toSig ring+      pure [f, a, r]+   let outs = [+            in'+          , freqscale+          , freqoffset+          , decayscale+          ] <> concat resonators'+   addMonoUGen $ UGen (UGName_S (UTF8.fromString "Klank")) AR outs 1  {- 3 "Klank" - AR (1 outputs)
Vivid/UGens/Generators/Deterministic.hs view
@@ -1,9 +1,13 @@-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE+     DataKinds+   , OverloadedStrings+   #-} -{-# LANGUAGE NoIncoherentInstances #-}-{-# LANGUAGE NoMonomorphismRestriction #-}-{-# LANGUAGE NoUndecidableInstances #-}+{-# LANGUAGE+     NoIncoherentInstances+   , NoMonomorphismRestriction+   , NoUndecidableInstances+   #-}  module Vivid.UGens.Generators.Deterministic ( ---     blip
Vivid/UGens/Info.hs view
@@ -1,5 +1,7 @@-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE+     DataKinds+   , OverloadedStrings+   #-}  {-# LANGUAGE NoIncoherentInstances #-} {-# LANGUAGE NoMonomorphismRestriction #-}@@ -75,7 +77,7 @@ numRunningSynths =    addUGen $ UGen (UGName_S "NumRunningSynths") IR [] 1 --- } This is CPU-intensive: only use for debugging!+-- | This is CPU-intensive: only use for debugging! --  --   First argument is frequency of polling: the number of times per second to poll -- 
Vivid/UGens/Maths.hs view
@@ -76,11 +76,11 @@ leastChange = leastOrMostChange "LeastChange"  leastOrMostChange :: (ToSig s0 as, ToSig s1 as) => String -> s0 -> s1 -> SDBody' as Signal-leastOrMostChange sdName s0 s1 = do+leastOrMostChange ugenName s0 s1 = do    s0' <- toSig s0    s1' <- toSig s1    calcRate <- (maximum::Ord a=>[a]->a) <$> sequence (map getCalcRate [s0', s1'])-   addUGen $ UGen (UGName_S . UTF8.fromString $ sdName) calcRate [s0',s1'] 1+   addUGen $ UGen (UGName_S . UTF8.fromString $ ugenName) calcRate [s0',s1'] 1  -- | "Converts a linear range of values to an exponential range of values." -- 
Vivid/UGens/Reverbs.hs view
@@ -22,6 +22,7 @@ freeVerb = makeUGen    "FreeVerb" AR    (Vs::Vs '["in", "mix", "room", "damp"])+   -- Strangely in SC it's "0.33" instead of (1/3) (greater precision). If we want exact compatibility we should switch to match that:    (mix_ (1/3::Float), room_ (0.5::Float), damp_ (0.5::Float))  --- freeVerb2 ::
vivid.cabal view
@@ -1,7 +1,5 @@--- TODO: get the readme change from the github merge- name:                vivid-version:             0.4.2.4+version:             0.5.0.0 synopsis:            Sound synthesis with SuperCollider description:            Music and sound synthesis with SuperCollider.@@ -64,7 +62,10 @@     , Vivid.Actions.Scheduled     , Vivid.ByteBeat     , Vivid.Envelopes+    , Vivid.GlobalState+    , Vivid.NoGlobalState     , Vivid.NoPlugins+    , Vivid.NoPluginsNoGlobalState     , Vivid.OSC.Bundles     , Vivid.Randomness     , Vivid.SCServer@@ -141,6 +142,9 @@       --    0.11 doesn't exist yet       -- Try: "> 0.9.1.8 && < 0.11"     , bytestring+++    , cereal        -- Lower bound:       --    Just a guess -- 0.4.0.0 is >5 years old