{-# Language ScopedTypeVariables #-} -- | The port is a tool to route the auio signals between instruments. -- We can allocate the port at the instance of the instrument (at the note) -- and pass the reference in the note to another instrument. That instrument -- cn write a signal to the port or can read the singals. module Csound.Typed.GlobalState.Port( IsPort(..), mixPort, modifyPort, Port(..), freePort, PortCtrl(..), freePortCtrl ) where import Control.Monad import Control.Monad.Trans.Class import Csound.Dynamic import Csound.Typed.GlobalState.GE import Csound.Typed.GlobalState.SE import Csound.Typed.Types.Tuple import Csound.Typed.Types.Prim import Csound.Typed.GlobalState.Opcodes(freeChn, chnName, chnget, chnset, chngetK, chnsetK) -- port class class IsPort p where readPort :: Sigs a => p a -> SE a writePort :: Sigs a => p a -> a -> SE () mixPort :: (Sigs a) => IsPort port => port a -> a -> SE () mixPort p value = modifyPort p (value + ) modifyPort :: (Sigs a, IsPort port) => port a -> (a -> a) -> SE () modifyPort p f = do value <- readPort p writePort p $ f value -- port for audio signals newtype Port a = Port { unPort :: GE E } freePort :: forall a . Sigs a => SE (Port a) freePort = SE $ fmap (Port . return) $ freeChn instance Sigs a => Tuple (Port a) where tupleMethods = makeTupleMethods to from where to :: D -> Port a to = Port . toGE from :: Port a -> D from (Port e) = fromGE e instance Sigs a => Arg (Port a) where instance IsPort Port where readPort port = SE $ hideGEinDep $ do names <- getNames port return $ fmap (toTuple . return) $ mapM chnget names writePort port a = SE $ do (names, values) <- lift getNamesAndValues zipWithM_ chnset names values where getNamesAndValues = do names <- getNames port values <- fromTuple a return (names, values) ------------------------------------------------------------- -- ports for control signals newtype PortCtrl a = PortCtrl { unPortCtrl :: GE E } freePortCtrl :: forall a . Sigs a => SE (PortCtrl a) freePortCtrl = SE $ fmap (PortCtrl . return) $ freeChn instance Sigs a => Tuple (PortCtrl a) where tupleMethods = makeTupleMethods to from where to :: D -> PortCtrl a to = PortCtrl . toGE from :: PortCtrl a -> D from (PortCtrl e) = fromGE e instance Sigs a => Arg (PortCtrl a) where instance IsPort PortCtrl where readPort port = SE $ hideGEinDep $ do names <- getNamesCtrl port return $ fmap (toTuple . return) $ mapM chngetK names writePort port a = SE $ do (names, values) <- lift getNamesAndValues zipWithM_ chnsetK names values where getNamesAndValues = do names <- getNamesCtrl port values <- fromTuple a return (names, values) ------------------------------------------------------- getNames :: forall a . Sigs a => Port a -> GE [E] getNames (Port ref) = do idx <- ref return $ fmap (flip chnName idx) [1 .. (tupleArity ((error "No def here") :: a))] getNamesCtrl :: forall a . Sigs a => PortCtrl a -> GE [E] getNamesCtrl (PortCtrl ref) = do idx <- ref return $ fmap (flip chnName idx) [1 .. (tupleArity ((error "No def here") :: a))]