-- | A @VividAction m => m a@ can either be run immediately, be scheduled to run at a -- precise future time, or be used for non-realtime synthesis. -- -- Note that at the moment VividAction has MonadIO, but this won't be true in -- upcoming versions (as early as the next release) - so don't get used -- to it! {-# LANGUAGE KindSignatures #-} {-# LANGUAGE Rank2Types #-} {-# LANGUAGE NoIncoherentInstances #-} {-# LANGUAGE NoMonomorphismRestriction #-} {-# LANGUAGE NoUndecidableInstances #-} module Vivid.Actions.Class ( VividAction(..) -- , VA , callOSCAndSync , oscWSync ) where import Vivid.SC.Server.Types (BufferId, NodeId, SyncId(..)) import qualified Vivid.SC.Server.Commands as SCCmd import Vivid.OSC import Vivid.SynthDef.Types (SynthDef) 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 -- | Send an 'OSC' message to the SuperCollider server callOSC :: OSC -> m () callOSC = callBS . encodeOSC -- | Send a ByteString to the SuperCollider server. -- You usually want to use 'call' instead. callBS :: ByteString -> m () -- | Blocks until the server finishes processing commands sync :: m () -- | As the user, you probably don't want to use this: -- -- Many commands already include a \"sync\" -- e.g. -- 'makeBuffer' already syncs. -- -- When you do want to do an -- explicit sync you probably want to use 'sync' instead, or -- 'callOSCAndSync' waitForSync :: SyncId -> m () -- | Wait, in seconds wait :: Real n => n -> m () getTime :: m Timestamp newBufferId :: m BufferId newNodeId :: m NodeId newSyncId :: m SyncId fork :: m () -> m () -- | Send a synth definition to be loaded on the SC server -- -- Note that this is sort of optional -- if you don't call it, it'll be called the first time -- you call 'synth' with the SynthDef defineSD :: SynthDef a -> m () -- | Send an OSC message and wait for it to complete before returning callOSCAndSync :: VividAction m => OSC -> m () callOSCAndSync message = do now <- getTime syncId <- newSyncId callBS $ encodeOSCBundle $ OSCBundle now [Right message, Right $ SCCmd.sync syncId] waitForSync syncId -- | -- -- Maybe can dedupe with 'callOSCAndSync' oscWSync :: VividAction m => (SyncId -> m ()) -> m () oscWSync actionFromId = do syncId <- newSyncId actionFromId syncId waitForSync syncId -- type VA x = forall m. VividAction m => m x