packages feed

csound-expression-typed 0.2.1.0 → 0.2.2.0

raw patch · 23 files changed

+1032/−716 lines, 23 filesdep ~csound-expression-dynamicdep ~temporal-mediadep ~wl-pprintPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependency ranges changed: csound-expression-dynamic, temporal-media, wl-pprint

API changes (from Hackage documentation)

- Csound.Typed.Gui: Display :: SE Gui -> Display
- Csound.Typed.Gui: Sink :: SE (Gui, Output a) -> Sink a
- Csound.Typed.Gui: SinkSource :: SE (Gui, Output a, Input a) -> SinkSource a
- Csound.Typed.Gui: Source :: SE (Gui, Input a) -> Source a
- Csound.Typed.Gui: [unDisplay] :: Display -> SE Gui
- Csound.Typed.Gui: [unSinkSource] :: SinkSource a -> SE (Gui, Output a, Input a)
- Csound.Typed.Gui: [unSink] :: Sink a -> SE (Gui, Output a)
- Csound.Typed.Gui: [unSource] :: Source a -> SE (Gui, Input a)
- Csound.Typed.Gui: newtype Display
- Csound.Typed.Gui: newtype Sink a
- Csound.Typed.Gui: newtype SinkSource a
- Csound.Typed.Gui: newtype Source a
+ Csound.Typed.Gui: type Display = SE Gui
+ Csound.Typed.Gui: type Sink a = SE (Gui, Output a)
+ Csound.Typed.Gui: type SinkSource a = SE (Gui, Output a, Input a)
+ Csound.Typed.Gui: type Source a = SE (Gui, Input a)
+ Csound.Typed.Plugins: tapeEcho :: D -> Sig -> Sig -> Sig -> Sig -> Sig -> Sig -> Sig
+ Csound.Typed.Types.Evt: instance Data.Default.Class.Default (Csound.Typed.Types.Evt.Evt a)
+ Csound.Typed.Types.Prim: getBpm :: Sig
+ Csound.Typed.Types.Prim: instance Data.String.IsString Csound.Typed.Types.Prim.Str
+ Csound.Typed.Types.Prim: setBpm :: Sig -> SE ()
- Csound.Typed.Control: type CsdEventList a = Track D a
+ Csound.Typed.Control: type CsdEventList a = Track Sig a
- Csound.Typed.Control: type Sco a = Track D a
+ Csound.Typed.Control: type Sco a = Track Sig a

Files

csound-expression-typed.cabal view
@@ -1,5 +1,5 @@ Name:          csound-expression-typed-Version:       0.2.1.0+Version:       0.2.2.0 Cabal-Version: >= 1.22 License:       BSD3 License-file:  LICENSE@@ -64,7 +64,7 @@   Ghc-Options:    -Wall   Build-Depends:         base >= 4, base < 5, ghc-prim, containers, transformers >= 0.3, Boolean >= 0.1.0, colour >= 2.0, data-default, deepseq, NumInstances, filepath, directory,-        wl-pprint, csound-expression-dynamic >= 0.3.2, temporal-media >= 0.6.0, hashable+        wl-pprint >= 1.2.1, csound-expression-dynamic >= 0.3.3, temporal-media >= 0.6.3, hashable   Hs-Source-Dirs:      src/   Exposed-Modules:     Csound.Typed@@ -118,6 +118,8 @@      Csound.Typed.Gui.Gui     Csound.Typed.Gui.Widget+    Csound.Typed.Gui.Pretty+    Csound.Typed.Gui.Types     Csound.Typed.Gui.BoxModel     Csound.Typed.Gui.Cabbage.CabbageLang     Csound.Typed.Gui.Cabbage.Cabbage
data/opcodes/MultiFX/TapeEcho.udo view
@@ -87,3 +87,27 @@   aProc bandpassCheby1 aOut * kFbGain, 95, 3000, iOrder, iRippleDb   delayw aIn + aProc * kFbGain endop++opcode tapeReadBatch, a, akkii+  aIn, kDelay, kRandomSpread, iSize, iStart xin++  if iStart <= iSize then+    acall tapeReadBatch aIn, kDelay, kRandomSpread, iSize, iStart + 1+  else+    acall = 0+  endif++  iScale = iStart+  aEcho tapeRead aIn, kDelay * iScale, kRandomSpread+  xout acall + aEcho / iScale+endop++opcode TapeEchoN, a, akkkkki+  aIn, kDelay, kEchoGain, kFbGain, kTone, kRandomSpread, iSize xin+  aDummy delayr (16 * iSize)+  aEcho tapeReadBatch aIn, kDelay, kRandomSpread, iSize, 1+  aOut = aIn + kEchoGain * aEcho+  tapeWrite aIn, aOut, kFbGain+  xout aOut+endop+
src/Csound/Typed/Control/Api.hs view
@@ -24,7 +24,7 @@ -- | Creates an instrument that can be triggered by name with Csound API. -- The arguments are determined from the structure of the input for the instrument. ----- With Csound API we can send messages +-- With Csound API we can send messages -- -- > i "name" time duration arg1 arg2 arg3 trigByName_ :: Arg a => String -> (a -> SE ()) -> SE ()@@ -34,14 +34,14 @@ -- The arguments are determined from the structure of the input for the instrument. -- If we have a tuple of arguments: @(D, D, Tab)@ -- The would be rendered to instrument arguments that strts from @p4@.--- @p1@ is the name of teh instrument, @p2@ is the start time of the note, +-- @p1@ is the name of teh instrument, @p2@ is the start time of the note, -- @p3@ is the duration of the note. Then @p4@ and @p5@ are going to be doubles and @p6@ -- is an integer that denotes a functional table. trigByName  :: (Arg a, Sigs b) => String -> (a -> SE b) -> SE b trigByName name instr = do     ref <- newClearableGlobalRef 0     trigByName_ name (go ref)-    readRef ref    +    readRef ref     where go ref x = mixRef ref =<< instr x  @@ -57,7 +57,7 @@             pchExpr      <- toGE pch             let instrIdExpr = D.instrIdE instrId + pchExpr / 1000             noteFlagExpr <- toGE noteFlag-            args <- fromTuple (pch, vol, other)            +            args <- fromTuple (pch, vol, other)             return $ do                     D.when1 D.Ir (noteFlagExpr ==* 1) $ do                         eventi (Event instrIdExpr 0 (-1) args)@@ -79,7 +79,7 @@ -- -- The instrument takes a triplet of @(pitchKey, volumeKey, auxilliaryTuple)@. -- The order does matter. Please don't pass the @volumeKey@ as the first argument.--- The instrument expects the pitch key to be a first argument. +-- The instrument expects the pitch key to be a first argument.  -- Under the hood -- it creates held notes that are indexed by pitch. If you know the Csound it creates@@ -95,10 +95,10 @@ trigByNameMidi name instr = do     ref <- newClearableGlobalRef 0     trigByNameMidi_ name (go ref)-    readRef ref    +    readRef ref     where go ref x = mixRef ref =<< instr x -namedMonoMsg ::String -> SE MonoArg+namedMonoMsg :: String -> SE MonoArg namedMonoMsg name = do     refPch <- newGlobalRef 0     refVol <- newGlobalRef 0@@ -116,18 +116,18 @@     let kgate = ifB onFlag 1 0         kamp = downsamp' volKey         kcps = downsamp' pchKey-        trig = changed [kamp, kcps] +        trig = changed [kamp, kcps]     return $ MonoArg kamp kcps kgate trig-    where        -        onNote = tabQueue2_append        +    where+        onNote = tabQueue2_append         offNote tab (pch, vol) = tabQueue2_delete tab pch  trigByNameMidiCbk :: String -> ((D, D) -> SE ())  -> ((D, D) -> SE ()) -> SE ()-trigByNameMidiCbk name noteOn noteOff = +trigByNameMidiCbk name noteOn noteOff =     trigByName_ name go     where         go :: (D, D, D) -> SE ()-        go (noteFlag, pch, vol) = do            +        go (noteFlag, pch, vol) = do             whenD1 (noteFlag ==* 1) $ noteOn (pch, vol)             whenD1 (noteFlag ==* 0) $ noteOff (pch, vol)             SE turnoff@@ -140,10 +140,10 @@  downsamp' :: Sig -> Sig downsamp' a = fromGE $ do-    a' <- toGE a    +    a' <- toGE a     return $ downsamp a' --- | +-- | -- Fast table opcodes. -- -- Fast table opcodes. Faster than@@ -163,7 +163,7 @@     where f a1 a2 a3 = opcs "tabw" [(Xr,[Kr,Kr,Ir,Ir])] [a1,a2,a3]  --- | +-- | -- Fast table opcodes. -- -- Fast table opcodes. Faster than
src/Csound/Typed/Control/Evt.hs view
@@ -31,7 +31,7 @@ import Csound.Typed.Constants(infiniteDur) import Csound.Typed.InnerOpcodes -renderEvts :: Evt (Sco a) -> Evt [(D, D, a)]+renderEvts :: Evt (Sco a) -> Evt [(Sig, Sig, a)] renderEvts = fmap (fmap unEvt . T.render)     where unEvt e = (T.eventStart e, T.eventDur e, T.eventContent e) @@ -55,7 +55,7 @@ ------------------------------------------------- -- triggereing the events -saveEvtInstr :: Arg a => Int -> C.InstrId -> Evt [(D, D, a)] -> GE C.InstrId+saveEvtInstr :: Arg a => Int -> C.InstrId -> Evt [(Sig, Sig, a)] -> GE C.InstrId saveEvtInstr arity instrId evts = saveInstr $ do     aliveCountRef <- newRef (10 :: D)     evtMixInstr aliveCountRef@@ -68,14 +68,14 @@             aliveCount <- readRef aliveCountRef             fromDep_ $ hideGEinDep $ liftA2 masterUpdateChnAlive chnId $ toGE aliveCount -        go :: Arg a => Ref D -> GE C.ChnRef -> Evt [(D, D, a)] -> SE ()+        go :: Arg a => Ref D -> GE C.ChnRef -> Evt [(Sig, Sig, a)] -> SE ()         go aliveCountRef mchnId events =             runEvt events $ \es -> do                 writeRef aliveCountRef $ int $ 2 * length es                 chnId <- geToSe mchnId                 fromDep_ $ mapM_ (event chnId) es -        event :: Arg a => C.ChnRef -> (D, D, a) -> Dep ()+        event :: Arg a => C.ChnRef -> (Sig, Sig, a) -> Dep ()         event chnId (start, dur, args) = hideGEinDep $ fmap C.event $             C.Event (primInstrId instrId) <$> toGE start <*> toGE dur <*> (fmap (++ [C.chnRefId chnId]) $ toNote args) @@ -252,7 +252,7 @@             return $ C.autoOff dtE x  -saveEvtInstr_ :: Arg a => C.InstrId -> Evt [(D, D, a)] -> Dep ()+saveEvtInstr_ :: Arg a => C.InstrId -> Evt [(Sig, Sig, a)] -> Dep () saveEvtInstr_ instrId evts = unSE $ runEvt evts $ \es -> fromDep_ $ mapM_ event es     where event (start, dur, args) = hideGEinDep $ fmap C.event $ C.Event (primInstrId instrId) <$> toGE start <*> toGE dur <*> toNote args @@ -289,7 +289,7 @@             I.writePort p (amp, cps, 0)             return $ MonoArg amp cps (ifB (gate `equalsTo` 0) 0 1) (changed [amp, cps, gate]) -runSco :: Arg a => Evt (Sco a) -> ((D,D,a) -> SE ()) -> SE ()+runSco :: Arg a => Evt (Sco a) -> ((Sig,Sig,a) -> SE ()) -> SE () runSco evts f = runEvt (renderEvts evts) $ mapM_ f  -- | Plays the note until next note comes or something happens on the second event stream.
src/Csound/Typed/Control/Instr.hs view
@@ -1,10 +1,10 @@ -- | Converts to low-level instruments module Csound.Typed.Control.Instr(-    Arity(..), InsExp, EffExp, -    funArity, constArity, -    insExp, effExp, masterExp, midiExp, unitExp, +    Arity(..), InsExp, EffExp,+    funArity, constArity,+    insExp, effExp, masterExp, midiExp, unitExp,     apInstr, apInstr0-) where    +) where  import Data.Default import Csound.Dynamic(InstrId(..))@@ -24,12 +24,12 @@  constArity :: (Tuple a) => SE a -> Arity constArity a = Arity 0 (outArity a)-   -insExp :: (Arg a, Tuple b) => (a -> SE b) -> InsExp ++insExp :: (Arg a, Tuple b) => (a -> SE b) -> InsExp insExp instr = execGEinSE $ fmap fromTuple $ instr toArg  effExp :: (Tuple a, Tuple b) => (a -> SE b) -> EffExp-effExp instr = execGEinSE . fmap fromTuple . instr . toTuple . return +effExp instr = execGEinSE . fmap fromTuple . instr . toTuple . return  masterExp :: (Tuple a) => SE a -> InsExp masterExp = execGEinSE . fmap fromTuple@@ -42,7 +42,7 @@  apInstr :: (Arg a, Sigs b) => GE InstrId -> a -> b apInstr instrIdGE args = res-    where +    where         res = toTuple $ do             instrId <- instrIdGE             argList <- fromTuple args
src/Csound/Typed/Control/Mix.hs view
@@ -1,4 +1,4 @@-{-# Language FlexibleContexts, ScopedTypeVariables #-}+{-# Language FlexibleContexts, ScopedTypeVariables, CPP #-} module Csound.Typed.Control.Mix(     Mix,     sco, eff, mix, mixBy, monoSco,@@ -8,17 +8,12 @@  import Data.Boolean -import Control.Applicative import Control.Monad.IO.Class-import Control.Monad.Trans.Class-import Control.Monad-import Data.Traversable import System.Mem.StableName  import Temporal.Media  import Csound.Dynamic hiding (Instr, Sco, str)-import qualified Csound.Typed.GlobalState.Elements as C  import Csound.Typed.Types import Csound.Typed.Types.MixSco@@ -26,10 +21,14 @@ import Csound.Typed.Control.Instr import Csound.Typed.InnerOpcodes +#if __GLASGOW_HASKELL__ < 710+import Data.Traversable+#endif+ toCsdEventList :: Sco a -> CsdEventList a toCsdEventList = id -singleCsdEvent :: (D, D, a) -> Sco a+singleCsdEvent :: (Sig, Sig, a) -> Sco a singleCsdEvent (start, duration, content) = del start $ str duration $ temp content  -- | Special type that represents a scores of sound signals.@@ -37,7 +36,7 @@ -- in the value of this type. newtype Mix a = Mix { unMix :: GE M } -type Sco a = Track D a+type Sco a = Track Sig a  wrapSco :: Sco a -> (CsdEventList a -> GE M) -> Sco (Mix b) wrapSco notes getContent = singleCsdEvent (0, csdEventListDur evts, Mix $ getContent evts)
src/Csound/Typed/Control/Ref.hs view
@@ -42,18 +42,18 @@ readRef  :: Tuple a => Ref a -> SE a readRef (Ref vars) = SE $ fmap (toTuple . return) $ mapM readVar vars --- | Allocates a new local (it is visible within the instrument) mutable value and initializes it with value. +-- | Allocates a new local (it is visible within the instrument) mutable value and initializes it with value. -- A reference can contain a tuple of variables. newRef :: Tuple a => a -> SE (Ref a)-newRef t = fmap Ref $ newLocalVars (tupleRates t) (fromTuple t)    -   --- | Allocates a new local (it is visible within the instrument) mutable value and initializes it with value. +newRef t = fmap Ref $ newLocalVars (tupleRates t) (fromTuple t)++-- | Allocates a new local (it is visible within the instrument) mutable value and initializes it with value. -- A reference can contain a tuple of variables. -- It contains control signals (k-rate) and constants for numbers (i-rates). newCtrlRef :: Tuple a => a -> SE (Ref a)-newCtrlRef t = fmap Ref $ newLocalVars (fmap toCtrlRate $ tupleRates t) (fromTuple t) -        -toCtrlRate x = case x of +newCtrlRef t = fmap Ref $ newLocalVars (fmap toCtrlRate $ tupleRates t) (fromTuple t)++toCtrlRate x = case x of     Ar -> Kr     Kr -> Ir     _  -> x@@ -79,7 +79,7 @@ -- | Modifies the Ref value with given function. modifyRef :: Tuple a => Ref a -> (a -> a) -> SE () modifyRef ref f = do-    v <- readRef ref      +    v <- readRef ref     writeRef ref (f v)  -- | An alias for the function @newRef@. It returns not the reference@@ -89,16 +89,16 @@     ref <- newRef a     return $ (readRef ref, writeRef ref) --- | Allocates a new global mutable value and initializes it with value. +-- | Allocates a new global mutable value and initializes it with value. -- A reference can contain a tuple of variables. newGlobalRef :: Tuple a => a -> SE (Ref a)-newGlobalRef t = fmap Ref $ newGlobalVars (tupleRates t) (fromTuple t)    +newGlobalRef t = fmap Ref $ newGlobalVars (tupleRates t) (fromTuple t) --- | Allocates a new global mutable value and initializes it with value. +-- | Allocates a new global mutable value and initializes it with value. -- A reference can contain a tuple of variables. -- It contains control signals (k-rate) and constants for numbers (i-rates). newGlobalCtrlRef :: Tuple a => a -> SE (Ref a)-newGlobalCtrlRef t = fmap Ref $ newGlobalVars (fmap toCtrlRate $ tupleRates t) (fromTuple t)   +newGlobalCtrlRef t = fmap Ref $ newGlobalVars (fmap toCtrlRate $ tupleRates t) (fromTuple t)  -- | An alias for the function @newRef@. It returns not the reference -- to mutable value but a pair of reader and writer functions.@@ -107,12 +107,12 @@     ref <- newRef a     return $ (readRef ref, writeRef ref) --- | Allocates a new clearable global mutable value and initializes it with value. +-- | Allocates a new clearable global mutable value and initializes it with value. -- A reference can contain a tuple of variables. -- The variable is set to zero at the end of every iteration. -- It's useful for accumulation of audio values from several instruments. newClearableGlobalRef :: Tuple a => a -> SE (Ref a)-newClearableGlobalRef t = fmap Ref $ newClearableGlobalVars (tupleRates t) (fromTuple t) +newClearableGlobalRef t = fmap Ref $ newClearableGlobalVars (tupleRates t) (fromTuple t)  ------------------------------------------------------------------------------- -- writable tables@@ -124,18 +124,18 @@ newTab :: D -> SE Tab newTab size = ftgentmp 0 0 size 7 0 [size, 0] --- | Creates a new global table. +-- | Creates a new global table. -- It's generated only once. It's persisted between instrument calls. -- -- > newGlobalTab identifier size newGlobalTab :: Int -> SE Tab-newGlobalTab size = do +newGlobalTab size = do     ref <- newGlobalCtrlRef ((fromGE $ saveWriteTab size) :: D)     fmap (fromGE . toGE) $ readRef ref  {-     identifier <- geToSe $ getNextGlobalGenId-    ref <- newGlobalRef (0 :: D)        +    ref <- newGlobalRef (0 :: D)     tabId <- ftgenonce 0 (Csound.Typed.Types.Prim.int identifier) size 7 0 [size, 0]     writeRef ref (fromGE $ toGE tabId)     fmap (fromGE . toGE) $ readRef ref@@ -145,10 +145,10 @@ -- some opcodes that I have to define upfront  --- | +-- | -- Generate a function table from within an instrument definition, without duplication of data. ----- Enables the creation of function tables entirely inside +-- Enables the creation of function tables entirely inside --       instrument definitions, without any duplication of data. -- -- > ifno  ftgenonce  ip1, ip2dummy, isize, igen, iarga, iargb, ...@@ -158,7 +158,7 @@ ftgenonce b1 b2 b3 b4 b5 b6 = fmap ( Tab . return) $ SE $ (depT =<<) $ lift $ f <$> unD b1 <*> unD b2 <*> unD b3 <*> unD b4 <*> unD b5 <*> mapM unD b6     where f a1 a2 a3 a4 a5 a6 = opcs "ftgenonce" [(Ir,(repeat Ir))] ([a1,a2,a3,a4,a5] ++ a6) --- | +-- | -- Generate a score function table from within the orchestra, which is deleted at the end of the note. -- -- Generate a score function table from within the orchestra,@@ -175,7 +175,7 @@  {- whileSE :: SE BoolSig -> SE () -> SE ()-whileSE mcond body = do      +whileSE mcond body = do     ref <- newCtrlRef $ (0 :: Sig)     writeCond ref     whileRefBegin ref@@ -205,8 +205,8 @@     writeRef refSt   =<< body    =<< readRef refSt     writeRef refCond =<< condSig =<< readRef refSt     fromDep_ whileEnd-    where  -        condSig :: st -> SE Sig               +    where+        condSig :: st -> SE Sig         condSig   = fmap (\b -> ifB b 1 0) . cond  @@ -218,8 +218,8 @@     writeRef refSt   =<< body    =<< readRef refSt     writeRef refCond =<< condSig =<< readRef refSt     fromDep_ whileEnd-    where   -        condSig :: st -> SE D              +    where+        condSig :: st -> SE D         condSig   = fmap (\b -> ifB b 1 0) . cond  whileRefBegin :: SigOrD a => Ref a -> SE ()
src/Csound/Typed/GlobalState/Elements.hs view
@@ -19,7 +19,7 @@     -- * Global variables     Globals(..), newPersistentGlobalVar, newClearableGlobalVar,     newPersistentGloabalArrVar,-    renderGlobals,+    renderGlobals, bpmVarName, bpmVar,     -- * Instruments     Instrs(..), saveInstr, getInstrIds, -- newInstrId, saveInstrById, saveInstr, CacheName, makeCacheName, saveCachedInstr, getInstrIds,     -- * Named instruments@@ -351,12 +351,17 @@         { allocArrVar :: Var         , allocArrVarSizes :: [E] } - data GlobalVarType = PersistentGlobalVar | ClearableGlobalVar     deriving (Eq)  instance Default Globals where-    def = Globals def def+    def = Globals 0 [AllocVar PersistentGlobalVar bpmVar 110]++bpmVar :: Var+bpmVar = Var GlobalVar Kr bpmVarName++bpmVarName :: String+bpmVarName = "gBpmVar"  newGlobalVar :: GlobalVarType -> Rate -> E -> State Globals Var newGlobalVar ty rate initVal = state $ \s ->
src/Csound/Typed/GlobalState/GE.hs view
@@ -3,7 +3,7 @@     GE, Dep, History(..), withOptions, withHistory, getOptions, evalGE, execGE,     getHistory, putHistory,     -- * Globals-    onGlobals,+    onGlobals, bpmVar,     -- * Midi     MidiAssign(..), Msg(..), renderMidiAssign, saveMidi, saveToMidiInstr,     MidiCtrl(..), saveMidiCtrl, renderMidiCtrl,
src/Csound/Typed/GlobalState/InstrApi.hs view
@@ -20,33 +20,45 @@  import qualified Csound.Typed.GlobalState.Opcodes as Opcodes(Event(..), event, eventi, turnoff2, turnoff, initSig, activeKr) -data InstrId a +data InstrId a     = InstrId { unInstrId :: GE E }     | InstrLinkedId { instrLivenessPort :: PortCtrl Sig, unInstrId :: GE E }  newInstr :: Arg a => (a -> SE ()) -> InstrId a newInstr instr = InstrId $ fmap instrIdE $ saveInstr (instr toArg) -event :: Arg a => InstrId a -> (D,D,a) -> SE ()+event :: Arg a => InstrId a -> (Sig,Sig,a) -> SE () event idx note = do     e <- getEvent idx note     SE $ Opcodes.event e  eventi :: Arg a => InstrId a -> (D,D,a) -> SE () eventi idx note = do-    e <- getEvent idx note+    e <- getEventi idx note     SE $ Opcodes.eventi e -getEvent :: Tuple a => InstrId a -> (D, D, a) -> SE Opcodes.Event+getEvent :: Tuple a => InstrId a -> (Sig, Sig, a) -> SE Opcodes.Event getEvent (InstrId idx) (start, dur, args) = SE $ lift $ do             i <- idx             s <- toGE start             d <- toGE dur             as <- fromTuple args             return $ Opcodes.Event i s d as-getEvent (InstrLinkedId port idx) (start, dur, arg) = do    +getEvent (InstrLinkedId port idx) (start, dur, arg) = do     getEvent (InstrId idx) (start, dur, (arg, port)) ++getEventi :: Tuple a => InstrId a -> (D, D, a) -> SE Opcodes.Event+getEventi (InstrId idx) (start, dur, args) = SE $ lift $ do+            i <- idx+            s <- toGE start+            d <- toGE dur+            as <- fromTuple args+            return $ Opcodes.Event i s d as+getEventi (InstrLinkedId port idx) (start, dur, arg) = do+    getEventi (InstrId idx) (start, dur, (arg, port))++ turnoff2 :: InstrId a -> SE () turnoff2 (InstrId expr) = SE $ Opcodes.turnoff2 =<< lift expr @@ -57,8 +69,8 @@ newInstrLinked instr = do     p <- freePortCtrl     writePort p 10-    let instrId = fmap instrIdE $ saveInstr (instr' toArg)        -    let resInstrId = InstrLinkedId p instrId    +    let instrId = fmap instrIdE $ saveInstr (instr' toArg)+    let resInstrId = InstrLinkedId p instrId     writePort p $ (fromGE $ fmap Opcodes.activeKr instrId) + 1     return resInstrId     where
src/Csound/Typed/GlobalState/Options.hs view
@@ -1,3 +1,4 @@+{-# Language CPP #-} module Csound.Typed.GlobalState.Options (     Options(..),     defGain, defSampleRate, defBlockSize, defTabFi, defScaleUI,@@ -50,16 +51,30 @@ instance Default Options where     def = Options def def def def def def def +#if MIN_VERSION_base(4,11,0)+instance Semigroup Options where+    (<>) = mappendOptions+ instance Monoid Options where-    mempty = def-    mappend a b = Options-        { csdFlags          = mappend (csdFlags a) (csdFlags b)-        , csdSampleRate     = csdSampleRate a <|> csdSampleRate b-        , csdBlockSize      = csdBlockSize a <|> csdBlockSize b-        , csdGain           = csdGain a <|> csdGain b-        , csdTabFi          = csdTabFi a <|> csdTabFi b-        , csdScaleUI        = csdScaleUI a <|> csdScaleUI b-        , csdJacko          = csdJacko a <|> csdJacko b }+    mempty  = def++#else++instance Monoid Options where+    mempty  = def+    mappend = mappendOptions++#endif++mappendOptions :: Options -> Options -> Options+mappendOptions a b = Options+    { csdFlags          = mappend (csdFlags a) (csdFlags b)+    , csdSampleRate     = csdSampleRate a <|> csdSampleRate b+    , csdBlockSize      = csdBlockSize a <|> csdBlockSize b+    , csdGain           = csdGain a <|> csdGain b+    , csdTabFi          = csdTabFi a <|> csdTabFi b+    , csdScaleUI        = csdScaleUI a <|> csdScaleUI b+    , csdJacko          = csdJacko a <|> csdJacko b }  defScaleUI :: Options -> (Double, Double) defScaleUI = maybe (1, 1) id . csdScaleUI
src/Csound/Typed/Gui/BoxModel.hs view
@@ -1,6 +1,6 @@-{-# Language DeriveFunctor #-}+{-# Language DeriveFunctor, CPP #-} module Csound.Typed.Gui.BoxModel(-    Rect(..), Offset(..), AbsScene(..), Scene(..),        +    Rect(..), Offset(..), AbsScene(..), Scene(..),     draw,     hor, ver, sca, margin, padding, space, prim,     appendContext, cascade, boundingRect, zeroRect@@ -12,13 +12,13 @@ import Data.Default import Data.Monoid -data Interval = Interval +data Interval = Interval     { start :: Int-    , leng  :: Int +    , leng  :: Int     } deriving (Show)-   + -- | A rectangle.-data Rect = Rect +data Rect = Rect     { px        :: Int     , py        :: Int     , width     :: Int@@ -30,27 +30,42 @@  toRect :: Interval -> Interval -> Rect toRect a b = Rect (start a) (start b) (leng a) (leng b)-  -data AbsScene ctx a ++data AbsScene ctx a     = Elem Rect a-    | EmptyScene +    | EmptyScene     | Group [AbsScene ctx a]     | Ctx Rect ctx (AbsScene ctx a)     deriving (Show)-     +++#if MIN_VERSION_base(4,11,0)+instance Semigroup (AbsScene ctx a) where+    (<>) = mappendAbsScene+ instance Monoid (AbsScene ctx a) where-    mempty = EmptyScene-    mappend a b = case (a, b) of-        (EmptyScene, _) -> b-        (_, EmptyScene) -> a        -        (Elem _ _, Group bs) -> Group (a:bs)-        (Group as, Elem _ _) -> Group (as ++ [b])-        (Group as, Group bs)   -> Group (as ++ bs)-        (_, _) -> Group [a, b]-   +    mempty  = EmptyScene++#else++instance Monoid (AbsScene ctx a) where+    mempty  = EmptyScene+    mappend = mappendAbsScene++#endif++mappendAbsScene :: AbsScene ctx a -> AbsScene ctx a -> AbsScene ctx a+mappendAbsScene a b = case (a, b) of+    (EmptyScene, _) -> b+    (_, EmptyScene) -> a+    (Elem _ _, Group bs) -> Group (a:bs)+    (Group as, Elem _ _) -> Group (as ++ [b])+    (Group as, Group bs)   -> Group (as ++ bs)+    (_, _) -> Group [a, b]+ data Scene ctx a     = Prim a-    | Space   +    | Space     | Scale Double (Scene ctx a)     | Hor Offset [Scene ctx a]     | Ver Offset [Scene ctx a]@@ -74,13 +89,13 @@                 Ver     o a -> Ver     o (fmap joinScene a)                 Context c a -> Context c (joinScene a) -data Offset = Offset +data Offset = Offset     { offsetOuter :: Int-    , offsetInner :: Int +    , offsetInner :: Int     } deriving (Show)  instance Default Offset where-    def = Offset +    def = Offset             { offsetOuter = 5             , offsetInner = 25 } @@ -91,7 +106,7 @@  hor, ver    :: [Scene a b] -> Scene a b space       :: Scene a b-prim        :: a -> Scene ctx a +prim        :: a -> Scene ctx a  sca :: Double -> Scene a b -> Scene a b margin, padding :: Int -> Scene a b -> Scene a b@@ -115,26 +130,26 @@ draw rect x = case x of     Space  -> mempty     Prim a -> Elem rect a-    Scale _ a -> draw rect a  -- no need to scale the rect we use +    Scale _ a -> draw rect a  -- no need to scale the rect we use                               -- scaling factor in the groups (hor/ver)     Hor off as -> composite (horRects rect) off as     Ver off as -> composite (verRects rect) off as     Context ctx a -> Ctx rect ctx (draw rect a)-    where +    where         composite getRects off as = mconcat $ zipWith draw (getRects off $ factors as) (fmap stripScale as)-   -        horRects r off scales = fmap (flip toRect commonSide) is ++        horRects r off scales = fmap (flip toRect commonSide) is             where commonSide = withoutMargin off iy-                  is = intervals off ix scales  +                  is = intervals off ix scales                   (ix, iy) = fromRect r -        verRects r off scales = fmap (toRect commonSide) is +        verRects r off scales = fmap (toRect commonSide) is             where commonSide = withoutMargin off ix-                  is = intervals off iy scales  -                  (ix, iy) = fromRect r  +                  is = intervals off iy scales+                  (ix, iy) = fromRect r  intervals :: Offset -> Interval -> [Double] -> [Interval]-intervals off total scales = evalState (mapM next scales') (start total') +intervals off total scales = evalState (mapM next scales') (start total')     where total'  = withoutMargin off total           leng'   = fromIntegral $ withoutPaddings off (length scales) (leng total')           scales' = fmap ( / s) scales@@ -142,7 +157,7 @@            next d  = state $ \soFar -> let l = round $ d * leng'                                       in  (Interval soFar l, soFar + l + offsetInner off)-            +           withoutPaddings offset n a = a - offsetInner offset * (n - 1)  withoutMargin :: Offset -> Interval -> Interval@@ -163,9 +178,9 @@ ----------------------------------------------- -- cascading update of the context -cascade :: -       (totalCtx -> Rect -> a -> res) -    -> res +cascade ::+       (totalCtx -> Rect -> a -> res)+    -> res     -> ([res] -> res)     -> (Rect -> ctx -> res -> res)     -> (ctx -> totalCtx -> totalCtx)@@ -188,8 +203,8 @@     Prim a      -> a     Space       -> zeroRect     Scale _ a   -> boundingRect a-    Hor ofs as  -> appHorOffset (length as) ofs $ horMerge $ fmap boundingRect as    -    Ver ofs as  -> appVerOffset (length as) ofs $ verMerge $ fmap boundingRect as    +    Hor ofs as  -> appHorOffset (length as) ofs $ horMerge $ fmap boundingRect as+    Ver ofs as  -> appVerOffset (length as) ofs $ verMerge $ fmap boundingRect as     Context _ a -> boundingRect a     where         appHorOffset n offset r = r { width  = appOffset n offset (width r)@@ -199,7 +214,7 @@                                     , width  = appOffset 1 offset (width r) }          appOffset n offset a = a-              + 2 * offsetOuter offset +              + 2 * offsetOuter offset               + (max (n - 1) 0) * offsetInner offset          horMerge = foldr iter zeroRect
src/Csound/Typed/Gui/Gui.hs view
@@ -6,12 +6,12 @@     guiStmt,      -- * Layout-    hor, ver, space, sca, horSca, verSca,     +    hor, ver, space, sca, horSca, verSca,     padding, margin, ScaleFactor, resizeGui,     -- * Props     props, forceProps,     Prop(..), BorderType(..), Color,-    Rect(..), FontType(..), Emphasis(..), +    Rect(..), FontType(..), Emphasis(..),     Material(..), Orient(..), LabelType(..),     -- ** Setters     -- | Handy short-cuts for the function @props@.@@ -31,7 +31,7 @@  import Prelude hiding(elem, span) -import Control.Applicative((<|>))+import Control.Applicative(Alternative(..)) import Data.Default import Data.Char(toLower) import Data.Maybe(isNothing)@@ -42,190 +42,31 @@ import Data.Colour.SRGB  import qualified Data.IntMap as IM-import Text.PrettyPrint.Leijen(Doc, int, double, vcat, hcat, hsep, punctuate, comma, empty, text, char, (<+>))---- import Csound.Render.Pretty(Doc, int, double, vcat, hcat, punctuate, comma)+import Text.PrettyPrint.Leijen(Doc)  import Csound.Dynamic(DepT, depT_, Var(..), VarType(..), Rate(..), noRate, MainExp(..), InstrId(..)) +import qualified Text.PrettyPrint.Leijen as P(int, double, vcat, hcat, hsep, punctuate, comma, empty, text, char, (<+>)) import qualified Csound.Typed.Gui.BoxModel as Box import Csound.Typed.Gui.BoxModel(Rect(..)) import Csound.Typed.Constants(infiniteDur) -newtype GuiHandle = GuiHandle { unGuiHandle :: Int }---- | The Csound colours. -type Color = Colour Double---- | The orientation of the widget (slider, roller). This property is --- never needs to be set in practice. If this property is not set then --- default orientation is calculated from the bounding box of the widget.--- If the width is greater than the height then we need to use a horizontal--- widget otherwise it should be a vertical one.-data Orient = Hor | Ver---- | A value span is a diapason of the value and a type --- of the scale (can be linear or exponential).-data ValSpan = ValSpan -    { valSpanDiap  :: ValDiap-    , valSpanScale :: ValScaleType }---- | Makes a linear @ValSpan@ with specified boundaries.------ > linSpan minVal maxVal-linSpan :: Double -> Double -> ValSpan-linSpan a b = ValSpan (ValDiap a b) Linear---- | Makes an exponential @ValSpan@ with specified boundaries.------ > expSpan minVal maxVal-expSpan :: Double -> Double -> ValSpan -expSpan a b = ValSpan (ValDiap (checkBound a) b) Exponential-    where-        checkBound x-            | x <= 0    = 0.00001-            | otherwise = x---- | Unit span. A special case:------ > uspan = linSpan 0 1-uspan :: ValSpan-uspan = linSpan 0 1---- | Bipolar unit span. A special case:------ > uspan = linSpan (-1) 1-bspan :: ValSpan-bspan = linSpan (-1) 1---- | An exponential unit span. A special case:------ > uspan = expSpan 0 1-uspanExp :: ValSpan-uspanExp = linSpan 0 1---- | The diapason of the continuous value.-data ValDiap = ValDiap -    { valDiapMin   :: Double -    , valDiapMax   :: Double }--data ValScaleType = Linear | Exponential--type ValStep = Double--data FontType       = Helvetica | Courier | Times | Symbol | Screen | Dingbats-data Emphasis       = NoEmphasis | Italic | Bold | BoldItalic-data KnobType       = ThreeD (Maybe Int) | Pie | Clock | Flat-data SliderType     = Fill | Engraved | Nice-data TextType       = NormalText | NoDrag | NoEdit---- | The type of the material of the element. It affects sliders and buttons.-data Material       = NoPlastic | Plastic---- | Some values are not implemented on the Csound level.-data LabelType      = NormalLabel | NoLabel | SymbolLabel -                    | ShadowLabel | EngravedLabel | EmbossedLabel---- | The type of the box. Some values are not implemented on the Csound level.-data BoxType    -    = FlatBox | UpBox | DownBox | ThinUpBox | ThinDownBox -    | EngravedBox | EmbossedBox | BorderBox | ShadowBox-    | Roundedbox | RoundedShadowBox | RoundedFlatBox-    | RoundedUpBox | RoundedDownBox | DiamondUpBox -    | DiamondDownBox | OvalBox | OvalShadowBox | OvalFlatBox-    deriving (Enum)--data BorderType-    = NoBorder | DownBoxBorder | UpBoxBorder | EngravedBorder -    | EmbossedBorder | BlackLine | ThinDown | ThinUp-    deriving (Enum)---- | The type of the button. It affects toggle buttons and button banks.------ In Csound buttons and toggle buttons--- are constructed with the same function (but with different button types). --- But in this library they are contructed by different functions (@button@ and @toggle@). --- Normal button is a plain old button, but other values specify toggle buttons.--- So this property doesn't affect the buttons (since they could be only normal buttons).-data ButtonType = NormalButton | LightButton | CheckButton | RoundButton--defFontSize :: Int-defFontSize = 15--instance Default FontType       where def = Courier-instance Default Emphasis       where def = NoEmphasis-instance Default SliderType     where def = Fill-instance Default KnobType       where def = Flat-instance Default TextType       where def = NormalText-instance Default ButtonType     where def = NormalButton-instance Default BoxType        where def = FlatBox-instance Default Material       where def = Plastic-instance Default LabelType      where def = NormalLabel--data InitMe = InitMe -    { initHandle :: Var-    , initValue  :: Double }--data Elem -    = GuiVar GuiHandle -    -    -- valuators-    | Count  ValDiap ValStep (Maybe ValStep)-    | Joy    ValSpan ValSpan-    | Knob   ValSpan-    | Roller ValSpan ValStep-    | Slider ValSpan-    | Text   ValDiap ValStep--    -- other widgets  -    | Box String-    | ButBank Int Int-    | Button InstrId-    | Toggle -    | Value-    | Vkeybd--data Props = Props -    { propsBorder   :: Maybe BorderType-    , propsScaleFactor :: Maybe ScaleFactor-    , otherProps    :: [Prop] }--type ScaleFactor = (Double, Double)--instance Monoid Props where-    mempty = Props Nothing Nothing []-    mappend a b = Props { propsBorder = propsBorder a <|> propsBorder b-                        , propsScaleFactor = propsScaleFactor a <|> propsScaleFactor b-                        , otherProps  = mappend (otherProps a) (otherProps b) }--instance Default Props where-    def = mempty+import Csound.Typed.Gui.Types+import Csound.Typed.Gui.Pretty --- | Properties of the widgets.-data Prop-    = SetLabel String-    | SetMaterial Material-    | SetBoxType BoxType-    | SetColor1 Color | SetColor2 Color | SetTextColor Color-    | SetFontSize Int | SetFontType FontType | SetEmphasis Emphasis-    | SetSliderType SliderType    -    | SetTextType TextType-    | SetButtonType ButtonType -    | SetOrient Orient-    | SetKnobType KnobType-    | SetLabelType LabelType+newtype GuiHandle = GuiHandle { unGuiHandle :: Int }  -- | A visual representation of the GUI-element. newtype Gui = Gui { unGui :: LowGui }  type LowGui = Box.Scene Props ElemWithOuts -data Panel -    = Single +data Panel+    = Single         { singleContent :: Win         , singleIsKeybdSensitive :: Bool }-    | Tabs -        { tabsTitle     :: String +    | Tabs+        { tabsTitle     :: String         , tabsRect      :: Maybe Rect         , tabsContent   :: [Win]         , tabsIsKeybdSensitive :: Bool }@@ -235,8 +76,8 @@     Single _ res -> res     Tabs _ _ _ res -> res -data Win = Win -    { winTitle :: String +data Win = Win+    { winTitle :: String     , winRect  :: Maybe Rect     , winGui   :: Gui } @@ -244,11 +85,34 @@     { guiNodeElem   :: Gui     , guiNodeHandle :: GuiHandle } -data ElemWithOuts = ElemWithOuts +data ElemWithOuts = ElemWithOuts     { elemOuts      :: [Var]     , elemInits     :: [InitMe]     , elemContent   :: Elem } +data InitMe = InitMe+    { initHandle :: Var+    , initValue  :: Double }++data Elem+    = GuiVar GuiHandle++    -- valuators+    | Count  ValDiap ValStep (Maybe ValStep)+    | Joy    ValSpan ValSpan+    | Knob   ValSpan+    | Roller ValSpan ValStep+    | Slider ValSpan+    | Text   ValDiap ValStep++    -- other widgets+    | Box String+    | ButBank Int Int+    | Button InstrId+    | Toggle+    | Value+    | Vkeybd+ type ElemOuts = [Var]  defText :: String -> Gui@@ -258,7 +122,7 @@ fromElem outs inits el = Gui $ Box.prim (ElemWithOuts outs inits el)  fromGuiHandle :: GuiHandle -> Gui-fromGuiHandle = Gui . Box.prim . ElemWithOuts [] [] . GuiVar +fromGuiHandle = Gui . Box.prim . ElemWithOuts [] [] . GuiVar  mapGuiOnPanel :: (Gui -> Gui) -> Panel -> Panel mapGuiOnPanel f x = case x of@@ -270,15 +134,15 @@ onLowGuis f = Gui . f . fmap unGui  onLowGui1 :: (LowGui -> LowGui) -> (Gui -> Gui)-onLowGui1 f = Gui . f . unGui +onLowGui1 f = Gui . f . unGui --- | Horizontal groupping of the elements. All elements are +-- | Horizontal groupping of the elements. All elements are -- placed in the stright horizontal line and aligned by Y-coordinate -- and height. hor :: [Gui] -> Gui-hor = onLowGuis Box.hor +hor = onLowGuis Box.hor --- | Vertical groupping of the elements. All elements are +-- | Vertical groupping of the elements. All elements are -- placed in the stright vertical line and aligned by X-coordinate -- and width. ver :: [Gui] -> Gui@@ -293,12 +157,12 @@ -- box is scaled. If it's a horizontal group then the width is scaled -- and height is scaled otherwise. ----- Every element in the group has a scaling factor. By +-- Every element in the group has a scaling factor. By -- default it equals to one. During rendering all scaling factors are summed--- and divided on the sum of all factors. So that factors become weights --- or proportions. This process is called normalization. --- Scaling one element affects not only this element but --- all other elements in the group! +-- and divided on the sum of all factors. So that factors become weights+-- or proportions. This process is called normalization.+-- Scaling one element affects not only this element but+-- all other elements in the group! -- -- An example: --@@ -317,12 +181,12 @@ sca :: Double -> Gui -> Gui sca d = onLowGui1 (Box.sca d) --- | Weighted horizontal grouping. +-- | Weighted horizontal grouping. -- It takes a list of scaling factors and elements. horSca :: [(Double, Gui)] -> Gui horSca ps = hor $ fmap (uncurry sca) ps --- | Weighted vertical grouping. +-- | Weighted vertical grouping. -- It takes a list of scaling factors and elements. verSca :: [(Double, Gui)] -> Gui verSca ps = ver $ fmap (uncurry sca) ps@@ -369,40 +233,40 @@ guiStmt defaultScaleUI panels = depT_ $ noRate (phi defaultScaleUI)     where phi scaleUI             | null panels = EmptyExp-            | otherwise   = Verbatim $ show $ vcat [vcat $ fmap (drawGui scaleUI) panels, text "FLrun"]+            | otherwise   = Verbatim $ show $ P.vcat [P.vcat $ fmap (drawGui scaleUI) panels, P.text "FLrun"]  drawGui :: ScaleFactor -> Panel -> Doc drawGui defaultScaleUI x = case x of     Single w    isKeybd -> panel isKeybd boundingRect $ drawWin (withWinMargin boundingRect) w-    Tabs _ _ ws isKeybd -> panel isKeybd tabPanelRect $ case ws of -        [] -> empty-        _  -> onTabs mainTabRect $ vcat $ fmap (uncurry $ drawTab shift) tabsRs        +    Tabs _ _ ws isKeybd -> panel isKeybd tabPanelRect $ case ws of+        [] -> P.empty+        _  -> onTabs mainTabRect $ P.vcat $ fmap (uncurry $ drawTab shift) tabsRs     where boundingRect = panelRect defaultScaleUI (fmap fst tabsRs) x-          tabsRs = tabsRects defaultScaleUI x  +          tabsRs = tabsRects defaultScaleUI x           (mainTabRect, shift) = mainTabRectAndShift boundingRect-    -          tabPanelRect = Rect ++          tabPanelRect = Rect             { px = 100             , py = 100             , width = width mainTabRect + 20-            , height = height mainTabRect + 20 +            , height = height mainTabRect + 20             }            panel = onPanel (panelTitle x) -          onPanel title isKeybdSensitive rect body = vcat +          onPanel title isKeybdSensitive rect body = P.vcat             -- panel with default position no border and capture of keyboard events-            [ ppProc "FLpanel" [ text $ show title, int $ width rect, int $ height rect, int (-1), int (-1), int 0-                               , int $ if isKeybdSensitive then 1 else 0 ]+            [ ppProc "FLpanel" [ P.text $ show title, P.int $ width rect, P.int $ height rect, P.int (-1), P.int (-1), P.int 0+                               , P.int $ if isKeybdSensitive then 1 else 0 ]             , body             , ppProc "FLpanelEnd" []] -          onTabs rect body = vcat +          onTabs rect body = P.vcat             [ ppProc "FLtabs" $ rectToFrame rect             , body             , ppProc "FLtabsEnd" []]-             + panelTitle :: Panel -> String panelTitle x = case x of     Single w _       -> winTitle w@@ -417,22 +281,22 @@     where boundingRect a b = Rect { px = x1, py = y1, width = x2 - x1, height = y2 - y1 }               where x1 = min (px a) (px b)                     y1 = min (py a) (py b)-                    x2 = max (px a + width a) (px b + width b) -                    y2 = max (py a + height a) (py b + height b)   +                    x2 = max (px a + width a) (px b + width b)+                    y2 = max (py a + height a) (py b + height b)  mainTabRectAndShift :: Rect -> (Rect, (Int, Int)) mainTabRectAndShift r = (res, (dx, dy))-    where res = Rect +    where res = Rect             { px     = 5-            , py     = 5    +            , py     = 5             , width  = px r + width r + 10             , height = py r + height r + yBox 15 2 + 10-            } +            }           dx = 10           dy = yBox 15 2 + 10-      + tabsRects :: ScaleFactor -> Panel -> [(Rect, Win)] tabsRects defaultScaleUI x = case x of     Single _ _    -> []@@ -440,69 +304,69 @@  winBoundingRect :: ScaleFactor -> Win -> Rect winBoundingRect defaultScaleUI w = maybe (shiftBy 50 $ bestRect defaultScaleUI $ winGui w) id $ winRect w-    where shiftBy n r = r { px = n + px r, py = n + py r }      +    where shiftBy n r = r { px = n + px r, py = n + py r }  drawTab :: (Int, Int) -> Rect -> Win -> Doc drawTab shift r w = group (winTitle w) r $ drawWin (withRelWinMargin $ shiftRect shift r) w-    where group title rect body = vcat -            [ ppProc "FLgroup" $ (text $ show title) : rectToFrame rect+    where group title rect body = P.vcat+            [ ppProc "FLgroup" $ (P.text $ show title) : rectToFrame rect             , body             , ppProc "FLgroupEnd" []] -          shiftRect (dx, dy) rect = rect +          shiftRect (dx, dy) rect = rect             { px = dx + px rect             , py = dy + py rect }-       + rectToFrame :: Rect -> [Doc]-rectToFrame rect = fmap int [width rect, height rect, px rect, py rect]                             +rectToFrame rect = fmap P.int [width rect, height rect, px rect, py rect]  drawWin :: Rect -> Win -> Doc drawWin rect w = renderAbsScene $ Box.draw rect $ unGui $ winGui w     where-        renderAbsScene = Box.cascade drawPrim empty vcat onCtx setProps def+        renderAbsScene = Box.cascade drawPrim P.empty P.vcat onCtx setProps def             where                 setProps ps = appEndo $ mconcat $ fmap (Endo . setPropCtx) (otherProps ps)-                +                 onCtx r ps res = maybe res (\borderType -> drawBorder borderType r res) (propsBorder ps)  drawBorder :: BorderType -> Rect -> Doc -> Doc-drawBorder borderType rect a = vcat -    [ ppProc "FLgroup" $ ((text $ show "") : frame) ++ [borderAsInt borderType]+drawBorder borderType rect a = P.vcat+    [ ppProc "FLgroup" $ ((P.text $ show "") : frame) ++ [borderAsInt borderType]     , a     , ppProc "FLgroupEnd" []]-    where borderAsInt = int . fromEnum-          frame = rectToFrame rect   -                +    where borderAsInt = P.int . fromEnum+          frame = rectToFrame rect+ drawPrim :: PropCtx -> Rect -> ElemWithOuts -> Doc-drawPrim ctx rect elem = vcat +drawPrim ctx rect elem = P.vcat     [ drawElemDef ctx rect elem     , drawAppearance ctx elem     , drawInitVal elem ]  drawAppearance :: PropCtx -> ElemWithOuts -> Doc-drawAppearance ctx el = maybe empty (flip flSetAll ctx)+drawAppearance ctx el = maybe P.empty (flip flSetAll ctx)     $ getPropHandle $ elemOuts el  drawInitVal :: ElemWithOuts -> Doc-drawInitVal = vcat . fmap flSetVal_i . elemInits +drawInitVal = P.vcat . fmap flSetVal_i . elemInits  drawElemDef :: PropCtx -> Rect -> ElemWithOuts -> Doc drawElemDef ctx rectWithoutLabel el = case elemContent el of     -- valuators     Count  diap step1 step2 -> drawCount diap step1 step2-    Joy    span1 span2      -> drawJoy span1 span2 -    Knob   span             -> drawKnob span -    Roller span step        -> drawRoller span step -    Slider span             -> drawSlider span -    Text   diap step        -> drawText diap step +    Joy    span1 span2      -> drawJoy span1 span2+    Knob   span             -> drawKnob span+    Roller span step        -> drawRoller span step+    Slider span             -> drawSlider span+    Text   diap step        -> drawText diap step -    -- other widgets  +    -- other widgets     Box label               -> drawBox label-    ButBank xn yn           -> drawButBank xn yn +    ButBank xn yn           -> drawButBank xn yn     Button instrId          -> drawButton instrId     Toggle                  -> drawToggle-    Value                   -> drawValue -    Vkeybd                  -> drawVkeybd +    Value                   -> drawValue+    Vkeybd                  -> drawVkeybd      -- error     GuiVar guiHandle        -> orphanGuiVar guiHandle@@ -514,27 +378,27 @@             where label = getLabel ctx          f = fWithLabel (getLabel ctx)-        fWithLabel label name args = ppMoOpc (fmap ppVar $ elemOuts el) name ((text $ show $ label) : args)+        fWithLabel label name args = ppMoOpc (fmap ppVar $ elemOuts el) name ((P.text $ show $ label) : args)         fNoLabel name args = ppMoOpc (fmap ppVar $ elemOuts el) name args         frame = frameBy rect         frameWithoutLabel = frameBy rectWithoutLabel-        frameBy x = fmap int [width x, height x, px x, py x]       -        noDisp = int (-1)-        noOpc  = int (-1)-        onOpc instrId xs = int 0 : int (instrIdCeil instrId) : fmap double xs+        frameBy x = fmap P.int [width x, height x, px x, py x]+        noDisp = P.int (-1)+        noOpc  = P.int (-1)+        onOpc instrId xs = P.int 0 : P.int (instrIdCeil instrId) : fmap P.double xs         drawSpan (ValSpan diap scale) = [imin diap, imax diap, getScale scale]-   -        imin = double . valDiapMin-        imax = double . valDiapMax +        imin = P.double . valDiapMin+        imax = P.double . valDiapMax+         -----------------------------------------------------------------------         -- valuators          -- FLcount         drawCount diap step1 mValStep2 = f "FLcount" $             [ imin diap, imax diap-            , double step1, double step2-            , int itype ] +            , P.double step1, P.double step2+            , P.int itype ]             ++ frame ++ [noOpc]             where (step2, itype) = case mValStep2 of                     -- type 1 FLcount with 2 steps@@ -546,14 +410,14 @@         drawJoy (ValSpan dX sX) (ValSpan dY sY) = f "FLjoy" $             [ imin dX, imax dX, imin dY, imax dY             , getScale sX, getScale sY-            , noDisp, noDisp +            , noDisp, noDisp             ] ++ frame          -- FLknob-        drawKnob span = f "FLknob" $ -            drawSpan span ++ [getKnobType ctx, noDisp] -            ++ fmap int knobFrame ++ getKnobCursorSize ctx            -            where +        drawKnob span = f "FLknob" $+            drawSpan span ++ [getKnobType ctx, noDisp]+            ++ fmap P.int knobFrame ++ getKnobCursorSize ctx+            where                 knobFrame                     | w < h     = [w, x, y + d]                     | otherwise = [h, x + d, y]@@ -561,231 +425,49 @@                 w = width rect                 x = px rect                 y = py rect-                d = div (abs $ h - w) 2 +                d = div (abs $ h - w) 2          -- FLroller         drawRoller (ValSpan d s) step = f "FLroller" $-            [ imin d, imax d, double step+            [ imin d, imax d, P.double step             , getScale s, getRollerType (getDefOrient rect) ctx, noDisp             ] ++ frame          -- FLslider-        drawSlider span = f "FLslider" $ -            drawSpan span -            ++ [getSliderType (getDefOrient rect) ctx, noDisp] +        drawSlider span = f "FLslider" $+            drawSpan span+            ++ [getSliderType (getDefOrient rect) ctx, noDisp]             ++ frame          -- FLtext-        drawText diap step = f "FLtext" $ -            [imin diap, imax diap, double step, getTextType ctx] ++ frame+        drawText diap step = f "FLtext" $+            [imin diap, imax diap, P.double step, getTextType ctx] ++ frame          -----------------------------------------------------------------------         -- other widgets-        +         -- FLbox         drawBox label = fWithLabel label "FLbox" $             [ getBoxType ctx, getFontType ctx, getFontSize ctx ] ++ frameWithoutLabel-        +         -- FLbutBank-        drawButBank xn yn = fNoLabel "FLbutBank" $ -            [getButtonBankType ctx, int xn, int yn] ++ frameWithoutLabel ++ [noOpc] +        drawButBank xn yn = fNoLabel "FLbutBank" $+            [getButtonBankType ctx, P.int xn, P.int yn] ++ frameWithoutLabel ++ [noOpc]          -- FLbutton's-        drawButton instrId = f "FLbutton" $ [int 1, int 0, getButtonType ctx] ++ frameWithoutLabel ++ (onOpc instrId [0, infiniteDur])-        -        drawToggle = f "FLbutton" $ [int 1, int 0, getToggleType ctx] ++ frameWithoutLabel ++ [noOpc]+        drawButton instrId = f "FLbutton" $ [P.int 1, P.int 0, getButtonType ctx] ++ frameWithoutLabel ++ (onOpc instrId [0, infiniteDur]) +        drawToggle = f "FLbutton" $ [P.int 1, P.int 0, getToggleType ctx] ++ frameWithoutLabel ++ [noOpc]+         -- FLvalue-        drawValue = f "FLvalue" frame +        drawValue = f "FLvalue" frame          -- FLvkeybd-        drawVkeybd = fWithLabel "" "FLvkeybd" frame  ---------------------------------------------------------------- cascading context, here we group properties by type--data PropCtx = PropCtx -    { ctxLabel        :: Maybe String-    , ctxMaterial     :: Maybe Material-    , ctxLabelType    :: Maybe LabelType-    , ctxBoxType      :: Maybe BoxType-    , ctxColor1       :: Maybe Color-    , ctxColor2       :: Maybe Color-    , ctxTextColor    :: Maybe Color-    , ctxFontSize     :: Maybe Int-    , ctxFontType     :: Maybe FontType-    , ctxEmphasis     :: Maybe Emphasis-    , ctxOrient       :: Maybe Orient-    , ctxSliderType   :: Maybe SliderType-    , ctxButtonType   :: Maybe ButtonType-    , ctxTextType     :: Maybe TextType-    , ctxKnobType     :: Maybe KnobType }-    -instance Default PropCtx where-    def = PropCtx Nothing Nothing Nothing Nothing Nothing Nothing-                  Nothing Nothing Nothing Nothing Nothing Nothing-                  Nothing Nothing Nothing -   -setPropCtx :: Prop -> PropCtx -> PropCtx -setPropCtx p x = case p of-            SetLabel        a -> x { ctxLabel  = Just a }-            SetMaterial     a -> x { ctxMaterial = Just a }-            SetLabelType    a -> x { ctxLabelType = Just a }-            SetBoxType      a -> x { ctxBoxType = Just a }-            SetColor1       a -> x { ctxColor1 = Just a }-            SetColor2       a -> x { ctxColor2 = Just a }-            SetTextColor    a -> x { ctxTextColor = Just a }-            SetFontSize     a -> x { ctxFontSize = Just a }-            SetFontType     a -> x { ctxFontType = Just a }-            SetEmphasis     a -> x { ctxEmphasis = Just a }-            SetOrient       a -> x { ctxOrient = Just a }-            SetSliderType   a -> x { ctxSliderType = Just a }-            SetButtonType   a -> x { ctxButtonType = Just a }-            SetTextType     a -> x { ctxTextType = Just a }-            SetKnobType     a -> x { ctxKnobType = Just a } --getLabel :: PropCtx -> String-getLabel = maybe "" id . ctxLabel----------------------------------------------------------------------- Converting readable properties to integer codes--maybeDef :: Default a => Maybe a -> a-maybeDef = maybe def id--intProp :: Default a => (PropCtx -> Maybe a) -> (a -> Int) -> (PropCtx -> Doc)-intProp select convert = int . convert . maybeDef . select --getScale :: ValScaleType -> Doc-getScale x = int $ case x of-    Linear      -> 0-    Exponential -> -1--getLabelType :: PropCtx -> Doc-getLabelType = intProp ctxLabelType $ \x -> case x of-    NormalLabel     -> 0-    NoLabel         -> 1-    SymbolLabel     -> 2-    ShadowLabel     -> 3-    EngravedLabel   -> 4-    EmbossedLabel   -> 5--getDefOrient :: Rect -> Orient-getDefOrient r -    | height r < width r    = Hor-    | otherwise             = Ver--getOrient :: Orient -> PropCtx -> Orient-getOrient defOrient = maybe defOrient id . ctxOrient--getKnobType :: PropCtx -> Doc-getKnobType = intProp ctxKnobType $ \x -> case x of-    Flat        -> 4-    Pie         -> 2-    Clock       -> 3-    ThreeD _    -> 1-  -getKnobCursorSize :: PropCtx -> [Doc]-getKnobCursorSize ctx = case maybeDef $ ctxKnobType ctx of-    ThreeD (Just n) -> [int n]-    _               -> []--getRollerType :: Orient -> PropCtx -> Doc-getRollerType defOrient ctx = int $ case getOrient defOrient ctx of-    Hor -> 1-    Ver -> 2-    -getSliderType :: Orient -> PropCtx -> Doc-getSliderType defOrient ctx = int $ appMaterial ctx $ -    case (getOrient defOrient ctx, maybeDef $ ctxSliderType ctx) of-        (Hor, Fill)         -> 1-        (Ver, Fill)         -> 2-        (Hor, Engraved)     -> 3-        (Ver, Engraved)     -> 4-        (Hor, Nice)         -> 5-        (Ver, Nice)         -> 6--getTextType :: PropCtx -> Doc-getTextType = intProp ctxTextType $ \x -> case x of  -    NormalText  -> 1-    NoDrag      -> 2-    NoEdit      -> 3--getBoxType :: PropCtx -> Doc-getBoxType = intProp ctxBoxType $ succ . fromEnum--getFontSize :: PropCtx -> Doc -getFontSize  = int . getIntFontSize --getIntFontSize :: PropCtx -> Int-getIntFontSize ctx = maybe defFontSize id $ ctxFontSize ctx--getFontType :: PropCtx -> Doc-getFontType ctx = int $ -    case (maybeDef $ ctxFontType ctx, maybeDef $ ctxEmphasis ctx) of-        (Helvetica, NoEmphasis)         -> 1-        (Helvetica, Bold)               -> 2-        (Helvetica, Italic)             -> 3-        (Helvetica, BoldItalic)         -> 4-        (Courier, NoEmphasis)           -> 5-        (Courier, Bold)                 -> 6-        (Courier, Italic)               -> 7-        (Courier, BoldItalic)           -> 8-        (Times, NoEmphasis)             -> 9-        (Times, Bold)                   -> 10-        (Times, Italic)                 -> 11-        (Times, BoldItalic)             -> 12-        (Symbol, _)                     -> 13-        (Screen, Bold)                  -> 15-        (Screen, _)                     -> 14-        (Dingbats, _)                   -> 16-       -getButtonType :: PropCtx -> Doc-getButtonType ctx = int $ appMaterial ctx 1--getButtonBankType :: PropCtx -> Doc-getButtonBankType ctx = ($ ctx) $ intProp ctxButtonType $ \x -> -    reactOnNoPlasticForRoundBug $ appMaterial ctx $ case x of-        NormalButton    -> 1-        LightButton     -> 2-        CheckButton     -> 3-        RoundButton     -> 4   -    where reactOnNoPlasticForRoundBug x = case x of-            24 -> 4-            _  -> x-       -getToggleType :: PropCtx -> Doc-getToggleType ctx = ($ ctx) $ intProp ctxButtonType $ \x -> -    reactOnNoPlasticForRoundBug $ appMaterial ctx $ case x of-        NormalButton    -> 2-        LightButton     -> 2-        CheckButton     -> 3-        RoundButton     -> 4   -    where reactOnNoPlasticForRoundBug x = case x of-            24 -> 4-            _  -> x---appMaterial :: PropCtx -> Int -> Int-appMaterial ctx = case maybeDef $ ctxMaterial ctx of-    Plastic   -> (+ 20)-    NoPlastic -> id-  -getColor1, getColor2, getTextColor :: PropCtx -> Doc--getColor1       = genGetColor gray  ctxColor1-getColor2       = genGetColor white ctxColor2-getTextColor    = genGetColor black ctxTextColor--genGetColor :: Color -> (PropCtx -> Maybe Color) -> PropCtx -> Doc-genGetColor defColor select ctx = colorToDoc $ maybe defColor id $ select ctx-    where colorToDoc col = hcat $ punctuate comma -            $ fmap (channelToDoc col) [channelRed, channelGreen, channelBlue]        -          channelToDoc col chn = int $ fromEnum $ chn $ toSRGB24 $ col  +        drawVkeybd = fWithLabel "" "FLvkeybd" frame  ----------------------------------------------------------------- -- handy shortcuts-    + setProp :: Prop -> Gui -> Gui setProp p = props [p] @@ -843,39 +525,39 @@  winMargin :: Int winMargin = 10-     + appendWinMargin :: Rect -> Rect-appendWinMargin r = r +appendWinMargin r = r     { width  = 2 * winMargin + width r-    , height = 2 * winMargin + height r +    , height = 2 * winMargin + height r     }  withWinMargin :: Rect -> Rect-withWinMargin r = r +withWinMargin r = r     { px = winMargin-    , py = winMargin +    , py = winMargin     , height = height r - 2 * winMargin-    , width  = width  r - 2 * winMargin +    , width  = width  r - 2 * winMargin     }  withRelWinMargin :: Rect -> Rect-withRelWinMargin r = r +withRelWinMargin r = r     { px = winMargin + px r     , py = winMargin + py r     , height = height r - 2 * winMargin-    , width  = width  r - 2 * winMargin +    , width  = width  r - 2 * winMargin     }  bestRect :: ScaleFactor -> Gui -> Rect bestRect defaultScaleUI-    = appendWinMargin . Box.boundingRect +    = appendWinMargin . Box.boundingRect     . mapWithOrientAndScale defaultScaleUI (\curOrient curScaleFactor x -> uncurry noShiftRect $ bestElemSizesRescaled curScaleFactor $ bestElemSizes curOrient $ elemContent x)     . unGui     where noShiftRect w h = Rect { px = 0, py = 0, width = w, height = h }-        + mapWithOrientAndScale :: ScaleFactor -> (Orient -> ScaleFactor -> a -> b) -> Box.Scene Props a -> Box.Scene Props b mapWithOrientAndScale defaultScaleUI f = iter Hor defaultScaleUI-    where +    where         iter curOrient curScale x = case x of             Box.Prim a          -> Box.Prim $ f curOrient curScale a             Box.Space           -> Box.Space@@ -885,35 +567,35 @@             Box.Context ctx a   -> case propsScaleFactor ctx of                     Nothing -> Box.Context ctx $ iter curOrient curScale a                     Just newScale -> Box.Context ctx $ iter curOrient (mulFactors curScale newScale) a-            where +            where                 mulFactors (x1, y1) (x2, y2) = (x1 * x2, y1 * y2)-       + bestElemSizesRescaled :: ScaleFactor -> (Int, Int) -> (Int, Int)-bestElemSizesRescaled (scaleX, scaleY) (sizeX, sizeY) = (mul scaleX sizeX, mul scaleY sizeY) -    where mul double int = round $ double * fromIntegral int+bestElemSizesRescaled (scaleX, scaleY) (sizeX, sizeY) = (mul scaleX sizeX, mul scaleY sizeY)+    where mul d n = round $ d * fromIntegral n  bestElemSizes :: Orient -> Elem -> (Int, Int) bestElemSizes orient x = case x of     -- valuators     Count   _ _ _   -> (120, 30)-    Joy     _ _     -> (200, 200)  +    Joy     _ _     -> (200, 200)     Knob    _       -> (80, 80)     Roller  _ _     -> inVer (150, 30)     Slider  _       -> inVer (150, 25)     Text    _ _     -> (100, 35) -    -- other widgets  -    Box     label    -> +    -- other widgets+    Box     label    ->         let symbolsPerLine = 60             numOfLines = succ $ div (length label) symbolsPerLine-        in  (xBox 15 symbolsPerLine, yBox 15 numOfLines)            +        in  (xBox 15 symbolsPerLine, yBox 15 numOfLines)      ButBank xn yn   -> (xn * 70, yn * 35)-    Button _        -> (75, 35) -    Toggle          -> (75, 35) +    Button _        -> (75, 35)+    Toggle          -> (75, 35)     Value           -> (80, 35)     Vkeybd          -> (1080, 240)-    +     -- error     GuiVar h        -> orphanGuiVar h     where inVer (a, b) = case orient of@@ -936,20 +618,20 @@ -- set properties  flSetAll :: Var -> PropCtx -> Doc-flSetAll handle ctx = vcat $ fmap (\f -> f handle ctx)+flSetAll handle ctx = P.vcat $ fmap (\f -> f handle ctx)     [ flSetColor, flSetColor2, flSetTextColor     , flSetTextSize, flSetTextType, flSetFont ] -flSetColor, flSetColor2, flSetTextColor, flSetTextSize, flSetTextType,     +flSetColor, flSetColor2, flSetTextColor, flSetTextSize, flSetTextType,     flSetFont :: Var -> PropCtx -> Doc -flSetProp :: String -    -> (PropCtx -> Maybe a) -    -> (PropCtx -> Doc) +flSetProp :: String+    -> (PropCtx -> Maybe a)+    -> (PropCtx -> Doc)     -> Var -> PropCtx -> Doc-flSetProp name isDef select handle ctx -    | isNothing $ isDef ctx = empty-    | otherwise             = ppProc name [select ctx, ppVar handle]    +flSetProp name isDef select handle ctx+    | isNothing $ isDef ctx = P.empty+    | otherwise             = ppProc name [select ctx, ppVar handle]  flSetColor        = flSetProp "FLsetColor"        ctxColor1       getColor1 flSetColor2       = flSetProp "FLsetColor2"       ctxColor2       getColor2@@ -959,7 +641,7 @@ flSetFont         = flSetProp "FLsetFont"         ctxFontType     getFontType  flSetVal_i :: InitMe -> Doc-flSetVal_i (InitMe handle v0) = ppProc "FLsetVal_i" [double v0, ppVar handle]+flSetVal_i (InitMe handle v0) = ppProc "FLsetVal_i" [P.double v0, ppVar handle]  ------------------------------------------------------------ -- extract handle.Hor@@ -974,34 +656,3 @@  orphanGuiVar :: GuiHandle -> a orphanGuiVar (GuiHandle n) = error $ "orphan GuiHandle: " ++ show n------------------------------------------------------------------ pretty printers--ppProc :: String -> [Doc] -> Doc-ppProc name xs = text name <+> (hsep $ punctuate comma xs)--ppMoOpc :: [Doc] -> String -> [Doc] -> Doc-ppMoOpc outs name ins = f outs <+> text name <+> f ins-    where f = hsep . punctuate comma--ppVar :: Var -> Doc-ppVar v = case v of-    Var ty rate name   -> hcat [ppVarType ty, ppRate rate, text (varPrefix ty : name)]-    VarVerbatim _ name -> text name--varPrefix :: VarType -> Char-varPrefix x = case x of-    LocalVar  -> 'l'-    GlobalVar -> 'g'--ppVarType :: VarType -> Doc-ppVarType x = case x of-    LocalVar  -> empty-    GlobalVar -> char 'g'--ppRate :: Rate -> Doc-ppRate x = case x of-    Sr -> char 'S'-    _  -> phi x-    where phi = text . map toLower . show 
+ src/Csound/Typed/Gui/Pretty.hs view
@@ -0,0 +1,192 @@+module Csound.Typed.Gui.Pretty (+  ppProc, ppMoOpc, ppVar, varPrefix, ppVarType, ppRate,++  intProp, getScale, getLabelType, getDefOrient, getOrient, getKnobType,+  getKnobCursorSize, getRollerType, getSliderType, getTextType, getBoxType,+  getFontSize, getIntFontSize, getFontType, getButtonType, getButtonBankType,+  getToggleType, appMaterial, getColor1, getColor2, getTextColor, genGetColor+) where++import Data.Char+import Data.Default+import Data.Colour.Names(white, gray, black)+import Data.Colour.SRGB++import Text.PrettyPrint.Leijen(Doc, int, hcat, hsep, punctuate, comma, text, char)+import qualified Text.PrettyPrint.Leijen as P((<+>), empty)++import Csound.Dynamic(Var(..), VarType(..), Rate(..))++import Csound.Typed.Gui.Types++-------------------------------------------------------------+-- pretty printers++ppProc :: String -> [Doc] -> Doc+ppProc name xs = text name P.<+> (hsep $ punctuate comma xs)++ppMoOpc :: [Doc] -> String -> [Doc] -> Doc+ppMoOpc outs name ins = f outs P.<+> text name P.<+> f ins+    where f = hsep . punctuate comma++ppVar :: Var -> Doc+ppVar v = case v of+    Var ty rate name   -> hcat [ppVarType ty, ppRate rate, text (varPrefix ty : name)]+    VarVerbatim _ name -> text name++varPrefix :: VarType -> Char+varPrefix x = case x of+    LocalVar  -> 'l'+    GlobalVar -> 'g'++ppVarType :: VarType -> Doc+ppVarType x = case x of+    LocalVar  -> P.empty+    GlobalVar -> char 'g'++ppRate :: Rate -> Doc+ppRate x = case x of+    Sr -> char 'S'+    _  -> phi x+    where phi = text . map toLower . show++------------------------------------------------------------------+-- Converting readable properties to integer codes++maybeDef :: Default a => Maybe a -> a+maybeDef = maybe def id++intProp :: Default a => (PropCtx -> Maybe a) -> (a -> Int) -> (PropCtx -> Doc)+intProp select convert = int . convert . maybeDef . select++getScale :: ValScaleType -> Doc+getScale x = int $ case x of+    Linear      -> 0+    Exponential -> -1++getLabelType :: PropCtx -> Doc+getLabelType = intProp ctxLabelType $ \x -> case x of+    NormalLabel     -> 0+    NoLabel         -> 1+    SymbolLabel     -> 2+    ShadowLabel     -> 3+    EngravedLabel   -> 4+    EmbossedLabel   -> 5++getDefOrient :: Rect -> Orient+getDefOrient r+    | height r < width r    = Hor+    | otherwise             = Ver++getOrient :: Orient -> PropCtx -> Orient+getOrient defOrient = maybe defOrient id . ctxOrient++getKnobType :: PropCtx -> Doc+getKnobType = intProp ctxKnobType $ \x -> case x of+    Flat        -> 4+    Pie         -> 2+    Clock       -> 3+    ThreeD _    -> 1++getKnobCursorSize :: PropCtx -> [Doc]+getKnobCursorSize ctx = case maybeDef $ ctxKnobType ctx of+    ThreeD (Just n) -> [int n]+    _               -> []++getRollerType :: Orient -> PropCtx -> Doc+getRollerType defOrient ctx = int $ case getOrient defOrient ctx of+    Hor -> 1+    Ver -> 2++getSliderType :: Orient -> PropCtx -> Doc+getSliderType defOrient ctx = int $ appMaterial ctx $+    case (getOrient defOrient ctx, maybeDef $ ctxSliderType ctx) of+        (Hor, Fill)         -> 1+        (Ver, Fill)         -> 2+        (Hor, Engraved)     -> 3+        (Ver, Engraved)     -> 4+        (Hor, Nice)         -> 5+        (Ver, Nice)         -> 6++getTextType :: PropCtx -> Doc+getTextType = intProp ctxTextType $ \x -> case x of+    NormalText  -> 1+    NoDrag      -> 2+    NoEdit      -> 3++getBoxType :: PropCtx -> Doc+getBoxType = intProp ctxBoxType $ (+1) . fromEnum++getFontSize :: PropCtx -> Doc+getFontSize  = int . getIntFontSize++getIntFontSize :: PropCtx -> Int+getIntFontSize ctx = maybe defFontSize id $ ctxFontSize ctx++getFontType :: PropCtx -> Doc+getFontType ctx = int $+    case (maybeDef $ ctxFontType ctx, maybeDef $ ctxEmphasis ctx) of+        (Helvetica, NoEmphasis)         -> 1+        (Helvetica, Bold)               -> 2+        (Helvetica, Italic)             -> 3+        (Helvetica, BoldItalic)         -> 4+        (Courier, NoEmphasis)           -> 5+        (Courier, Bold)                 -> 6+        (Courier, Italic)               -> 7+        (Courier, BoldItalic)           -> 8+        (Times, NoEmphasis)             -> 9+        (Times, Bold)                   -> 10+        (Times, Italic)                 -> 11+        (Times, BoldItalic)             -> 12+        (Symbol, _)                     -> 13+        (Screen, Bold)                  -> 15+        (Screen, _)                     -> 14+        (Dingbats, _)                   -> 16++++getButtonType :: PropCtx -> Doc+getButtonType ctx = int $ appMaterial ctx 1++getButtonBankType :: PropCtx -> Doc+getButtonBankType ctx = ($ ctx) $ intProp ctxButtonType $ \x ->+    reactOnNoPlasticForRoundBug $ appMaterial ctx $ case x of+        NormalButton    -> 1+        LightButton     -> 2+        CheckButton     -> 3+        RoundButton     -> 4++getToggleType :: PropCtx -> Doc+getToggleType ctx = ($ ctx) $ intProp ctxButtonType $ \x ->+    reactOnNoPlasticForRoundBug $ appMaterial ctx $ case x of+        NormalButton    -> 2+        LightButton     -> 2+        CheckButton     -> 3+        RoundButton     -> 4++reactOnNoPlasticForRoundBug :: Int -> Int+reactOnNoPlasticForRoundBug x+  | x == 24 = 4+  | otherwise = x++appMaterial :: PropCtx -> Int -> Int+appMaterial ctx = case maybeDef $ ctxMaterial ctx of+    Plastic   -> (+ 20)+    NoPlastic -> id++getColor1 :: PropCtx -> Doc+getColor1       = genGetColor gray  ctxColor1++getColor2 :: PropCtx -> Doc+getColor2       = genGetColor white ctxColor2++getTextColor :: PropCtx -> Doc+getTextColor    = genGetColor black ctxTextColor++genGetColor :: Color -> (PropCtx -> Maybe Color) -> PropCtx -> Doc+genGetColor defColor select ctx = colorToDoc $ maybe defColor id $ select ctx+    where+      colorToDoc col = hcat $ punctuate comma+            $ fmap (channelToDoc col) [channelRed, channelGreen, channelBlue]++      channelToDoc col chn = int $ fromEnum $ chn $ toSRGB24 $ col
+ src/Csound/Typed/Gui/Types.hs view
@@ -0,0 +1,249 @@+{-# Language CPP #-}+module Csound.Typed.Gui.Types (+    Props(..),+    Prop(..), BorderType(..), Color,+    Rect(..), FontType(..), Emphasis(..),+    Material(..), Orient(..), LabelType(..),+    ScaleFactor,++    ValDiap(..), ValStep, ValScaleType(..), ValSpan(..),+    linSpan, expSpan, uspan, bspan, uspanExp,+    KnobType(..),+    SliderType(..),+    TextType(..),+    BoxType(..),+    ButtonType(..),++    defFontSize,++    PropCtx(..), setPropCtx, getLabel+) where++#if __GLASGOW_HASKELL__ < 710+import Data.Monoid+#endif++import Control.Applicative(Alternative(..))+import Data.Default+import Data.Colour++import Csound.Typed.Gui.BoxModel(Rect(..))++-- | The Csound colours.+type Color = Colour Double++-- | The orientation of the widget (slider, roller). This property is+-- never needs to be set in practice. If this property is not set then+-- default orientation is calculated from the bounding box of the widget.+-- If the width is greater than the height then we need to use a horizontal+-- widget otherwise it should be a vertical one.+data Orient = Hor | Ver++-- | A value span is a diapason of the value and a type+-- of the scale (can be linear or exponential).+data ValSpan = ValSpan+    { valSpanDiap  :: ValDiap+    , valSpanScale :: ValScaleType }++-- | Makes a linear @ValSpan@ with specified boundaries.+--+-- > linSpan minVal maxVal+linSpan :: Double -> Double -> ValSpan+linSpan a b = ValSpan (ValDiap a b) Linear++-- | Makes an exponential @ValSpan@ with specified boundaries.+--+-- > expSpan minVal maxVal+expSpan :: Double -> Double -> ValSpan+expSpan a b = ValSpan (ValDiap (checkBound a) b) Exponential+    where+        checkBound x+            | x <= 0    = 0.00001+            | otherwise = x++-- | Unit span. A special case:+--+-- > uspan = linSpan 0 1+uspan :: ValSpan+uspan = linSpan 0 1++-- | Bipolar unit span. A special case:+--+-- > uspan = linSpan (-1) 1+bspan :: ValSpan+bspan = linSpan (-1) 1++-- | An exponential unit span. A special case:+--+-- > uspan = expSpan 0 1+uspanExp :: ValSpan+uspanExp = linSpan 0 1++-- | The diapason of the continuous value.+data ValDiap = ValDiap+    { valDiapMin   :: Double+    , valDiapMax   :: Double }++data ValScaleType = Linear | Exponential++type ValStep = Double++data FontType       = Helvetica | Courier | Times | Symbol | Screen | Dingbats+data Emphasis       = NoEmphasis | Italic | Bold | BoldItalic+data KnobType       = ThreeD (Maybe Int) | Pie | Clock | Flat+data SliderType     = Fill | Engraved | Nice+data TextType       = NormalText | NoDrag | NoEdit++-- | The type of the material of the element. It affects sliders and buttons.+data Material       = NoPlastic | Plastic++-- | Some values are not implemented on the Csound level.+data LabelType      = NormalLabel | NoLabel | SymbolLabel+                    | ShadowLabel | EngravedLabel | EmbossedLabel++-- | The type of the box. Some values are not implemented on the Csound level.+data BoxType+    = FlatBox+    | UpBox+    | DownBox+    | ThinUpBox+    | ThinDownBox+    | EngravedBox+    | EmbossedBox+    | BorderBox+    | ShadowBox+    | Roundedbox+    | RoundedShadowBox+    | RoundedFlatBox+    | RoundedUpBox+    | RoundedDownBox+    | DiamondUpBox+    | DiamondDownBox+    | OvalBox+    | OvalShadowBox+    | OvalFlatBox+    deriving (Enum)++data BorderType+    = NoBorder+    | DownBoxBorder+    | UpBoxBorder+    | EngravedBorder+    | EmbossedBorder+    | BlackLine+    | ThinDown+    | ThinUp+    deriving (Enum)++-- | The type of the button. It affects toggle buttons and button banks.+--+-- In Csound buttons and toggle buttons+-- are constructed with the same function (but with different button types).+-- But in this library they are contructed by different functions (@button@ and @toggle@).+-- Normal button is a plain old button, but other values specify toggle buttons.+-- So this property doesn't affect the buttons (since they could be only normal buttons).+data ButtonType = NormalButton | LightButton | CheckButton | RoundButton++defFontSize :: Int+defFontSize = 15++instance Default FontType       where def = Courier+instance Default Emphasis       where def = NoEmphasis+instance Default SliderType     where def = Fill+instance Default KnobType       where def = Flat+instance Default TextType       where def = NormalText+instance Default ButtonType     where def = NormalButton+instance Default BoxType        where def = FlatBox+instance Default Material       where def = Plastic+instance Default LabelType      where def = NormalLabel++data Props = Props+    { propsBorder   :: Maybe BorderType+    , propsScaleFactor :: Maybe ScaleFactor+    , otherProps    :: [Prop] }++type ScaleFactor = (Double, Double)++#if MIN_VERSION_base(4,11,0)+instance Semigroup Props where+    (<>) = mappendProps++instance Monoid Props where+    mempty  = def++#else++instance Monoid Props where+    mempty  = def+    mappend = mappendProps++#endif+++mappendProps :: Props -> Props -> Props+mappendProps a b = Props { propsBorder = propsBorder a <|> propsBorder b+                    , propsScaleFactor = propsScaleFactor a <|> propsScaleFactor b+                    , otherProps  = mappend (otherProps a) (otherProps b) }++instance Default Props where+    def = Props Nothing Nothing []++-- | Properties of the widgets.+data Prop+    = SetLabel String+    | SetMaterial Material+    | SetBoxType BoxType+    | SetColor1 Color | SetColor2 Color | SetTextColor Color+    | SetFontSize Int | SetFontType FontType | SetEmphasis Emphasis+    | SetSliderType SliderType+    | SetTextType TextType+    | SetButtonType ButtonType+    | SetOrient Orient+    | SetKnobType KnobType+    | SetLabelType LabelType++-----------------------------------------------------------+-- cascading context, here we group properties by type++data PropCtx = PropCtx+    { ctxLabel        :: Maybe String+    , ctxMaterial     :: Maybe Material+    , ctxLabelType    :: Maybe LabelType+    , ctxBoxType      :: Maybe BoxType+    , ctxColor1       :: Maybe Color+    , ctxColor2       :: Maybe Color+    , ctxTextColor    :: Maybe Color+    , ctxFontSize     :: Maybe Int+    , ctxFontType     :: Maybe FontType+    , ctxEmphasis     :: Maybe Emphasis+    , ctxOrient       :: Maybe Orient+    , ctxSliderType   :: Maybe SliderType+    , ctxButtonType   :: Maybe ButtonType+    , ctxTextType     :: Maybe TextType+    , ctxKnobType     :: Maybe KnobType }++instance Default PropCtx where+    def = PropCtx Nothing Nothing Nothing Nothing Nothing Nothing+                  Nothing Nothing Nothing Nothing Nothing Nothing+                  Nothing Nothing Nothing++setPropCtx :: Prop -> PropCtx -> PropCtx+setPropCtx p x = case p of+            SetLabel        a -> x { ctxLabel  = Just a }+            SetMaterial     a -> x { ctxMaterial = Just a }+            SetLabelType    a -> x { ctxLabelType = Just a }+            SetBoxType      a -> x { ctxBoxType = Just a }+            SetColor1       a -> x { ctxColor1 = Just a }+            SetColor2       a -> x { ctxColor2 = Just a }+            SetTextColor    a -> x { ctxTextColor = Just a }+            SetFontSize     a -> x { ctxFontSize = Just a }+            SetFontType     a -> x { ctxFontType = Just a }+            SetEmphasis     a -> x { ctxEmphasis = Just a }+            SetOrient       a -> x { ctxOrient = Just a }+            SetSliderType   a -> x { ctxSliderType = Just a }+            SetButtonType   a -> x { ctxButtonType = Just a }+            SetTextType     a -> x { ctxTextType = Just a }+            SetKnobType     a -> x { ctxKnobType = Just a }++getLabel :: PropCtx -> String+getLabel = maybe "" id . ctxLabel
src/Csound/Typed/Gui/Widget.hs view
@@ -7,7 +7,7 @@     -- * Types     Input(..), Output(..), Inner(..),     noInput, noOutput, noInner,-    Widget, widget, Source(..), source, Sink(..), sink, Display(..), display, SinkSource(..), sinkSource, sourceSlice, sinkSlice,+    Widget, widget, Source, source, Sink, sink, Display, display, SinkSource, sinkSource, sourceSlice, sinkSlice,     mapSource, mapGuiSource, mhor, mver, msca,      -- * Widgets@@ -124,29 +124,27 @@ type Widget a b = SE (Gui, Output a, Input b, Inner)  -- | A consumer of the values.-newtype Sink   a = Sink { unSink :: SE (Gui, Output a) }+type Sink   a = SE (Gui, Output a)  -- | A producer of the values.-newtype Source a = Source { unSource :: SE (Gui, Input a) }-    deriving (Functor)+type Source a = SE (Gui, Input a) -newtype SinkSource a = SinkSource { unSinkSource :: SE (Gui, Output a, Input a) }+type SinkSource a = SE (Gui, Output a, Input a)  -- | A static element. We can only look at it.-newtype Display  = Display { unDisplay :: SE Gui }-+type Display  = SE Gui  -- | A handy function for transforming the value of producers. mapSource :: (a -> b) -> Source a -> Source b-mapSource = fmap+mapSource f x = fmap (second f) x  -- | A handy function for transforming the GUIs of producers. mapGuiSource :: (Gui -> Gui) -> Source a -> Source a-mapGuiSource f (Source x) = Source $ fmap (\(gui, ins) -> (f gui, ins)) x+mapGuiSource f x = fmap (\(gui, ins) -> (f gui, ins)) x  mGroup :: Monoid a => ([Gui] -> Gui) -> [Source a] -> Source a-mGroup guiGroup as = Source $ do-    (gs, fs) <- fmap unzip $ sequence $ fmap unSource as+mGroup guiGroup as = do+    (gs, fs) <- fmap unzip $ sequence as     return (guiGroup gs, mconcat fs)  -- | Horizontal grouping of widgets that can produce monoidal values.@@ -173,27 +171,27 @@  -- | A producer constructor. source :: SE (Gui, Input a) -> Source a-source x = Source $ fmap select $ widget $ fmap append x+source x = fmap select $ widget $ fmap append x     where         select (g, _, i, _) = (g, i)         append (g, i) = (g, noOutput, i, noInner)  -- | A consumer constructor. sink :: SE (Gui, Output a) -> Sink a-sink x = Sink $ fmap select $ widget $ fmap append x+sink x = fmap select $ widget $ fmap append x     where         select (g, o, _, _) = (g, o)         append (g, o) = (g, o, noInput, noInner)  sinkSource :: SE (Gui, Output a, Input a) -> SinkSource a-sinkSource x = SinkSource $ fmap select $ widget $ fmap append x+sinkSource x = fmap select $ widget $ fmap append x     where         select (g, o, i, _) = (g, o, i)         append (g, o, i) = (g, o, i, noInner)  -- | A display constructor. display :: SE Gui -> Display-display x = Display $ fmap select $ widget $ fmap append x+display x = fmap select $ widget $ fmap append x     where         select (g, _, _, _) = g         append g = (g, noOutput, noInput, noInner)@@ -206,11 +204,11 @@ setTitle name g     | null name = return g     | otherwise = do-        gTitle <- unDisplay $ box name+        gTitle <- box name         return $ ver [sca 0.01 gTitle, g]  setSourceTitle :: String -> Source a -> Source a-setSourceTitle name (Source ma) = source $ do+setSourceTitle name ma = source $ do     (gui, val) <- ma     newGui <- setTitle name gui     return (newGui, val)@@ -218,20 +216,20 @@ setLabelSource :: String -> Source a -> Source a setLabelSource a     | null a    = id-    | otherwise = Source . fmap (first $ setLabel a) . unSource+    | otherwise = fmap (first $ setLabel a)  setLabelSink :: String -> Sink a -> Sink a setLabelSink a     | null a    = id-    | otherwise = Sink . fmap (first $ setLabel a) . unSink+    | otherwise = fmap (first $ setLabel a)  setLabelSnkSource :: String -> SinkSource a -> SinkSource a setLabelSnkSource a     | null a    = id-    | otherwise = SinkSource . fmap (\(x, y, z) -> (setLabel a x, y, z)) . unSinkSource+    | otherwise = fmap (\(x, y, z) -> (setLabel a x, y, z))  singleOut :: Maybe Double -> Elem -> Source Sig-singleOut v0 el = Source $ geToSe $ do+singleOut v0 el = geToSe $ do     (var, handle) <- newGuiVar     let handleVar = guiHandleToVar handle         inits = maybe [] (return . InitMe handleVar) v0@@ -240,7 +238,7 @@     return (fromGuiHandle handle, readSig var)  singleIn :: (GuiHandle -> Output Sig) -> Maybe Double -> Elem -> Sink Sig-singleIn outs v0 el = Sink $ geToSe $ do+singleIn outs v0 el = geToSe $ do     (var, handle) <- newGuiVar     let handleVar = guiHandleToVar handle         inits = maybe [] (return . InitMe handleVar) v0@@ -249,7 +247,7 @@     return (fromGuiHandle handle, outs handle)  singleInOut :: (GuiHandle -> Output Sig) -> Maybe Double -> Elem -> SinkSource Sig-singleInOut outs v0 el = SinkSource $ geToSe $ do+singleInOut outs v0 el = geToSe $ do     (var, handle) <- newGuiVar     let handleVar = guiHandleToVar handle         inits = maybe [] (return . InitMe handleVar) v0@@ -279,7 +277,7 @@ -- -- doc: <http://www.csounds.com/manual/html/FLjoy.html> joy :: ValSpan -> ValSpan -> (Double, Double) -> Source (Sig, Sig)-joy sp1 sp2 (x, y) = Source $ geToSe $ do+joy sp1 sp2 (x, y) = geToSe $ do     (var1, handle1) <- newGuiVar     (var2, handle2) <- newGuiVar     let handleVar1 = guiHandleToVar handle1@@ -318,7 +316,7 @@ -- of init values. sliderBank :: String -> [Double] -> Source [Sig] sliderBank name ds = source $ do-    (gs, vs) <- fmap unzip $ zipWithM (\n d -> unSource $ slider (show n) uspan d) [(1::Int) ..] ds+    (gs, vs) <- fmap unzip $ zipWithM (\n d -> slider (show n) uspan d) [(1::Int) ..] ds     gui <- setTitle name  $ hor gs     return (gui, vs) @@ -341,7 +339,7 @@ box :: String -> Display box label     | length label < lim = rawBox label-    | otherwise          = Display $ fmap (padding 0 . ver) $ mapM (unDisplay . rawBox) $ parts lim label+    | otherwise          = fmap (padding 0 . ver) $ mapM rawBox $ parts lim label     where         parts n xs             | length xs < n = [xs]@@ -350,7 +348,7 @@         lim = 255  rawBox :: String -> Display-rawBox label = Display $ geToSe $ do+rawBox label = geToSe $ do     (_, handle) <- newGuiVar     let gui = fromElem [guiHandleToVar handle] [] (Box label)     appendToGui (GuiNode gui handle) (unSE noInner)@@ -367,7 +365,7 @@     flagChanged <- geToSe $ onGlobals $ C.newPersistentGlobalVar Kr 0     instrId <- geToSe $ saveInstr $ instr flag     geToSe $ (saveAlwaysOnInstr =<< ) $ saveInstr $ instrCh flag flagChanged-    (g, _) <- unSource $ singleOut Nothing (Button instrId)+    (g, _) <- singleOut Nothing (Button instrId)     val <- fmap fromGE $ fromDep $ readVar flagChanged     return (g, sigToEvt val)     where@@ -451,7 +449,7 @@  setToggle :: String -> Bool -> SinkSource (Evt D) setToggle name initVal = sinkSource $ do-    (g, outs, ins) <- unSinkSource $ setToggleSig name initVal+    (g, outs, ins) <- setToggleSig name initVal     let evtOuts a = outs =<< stepper 0 (fmap sig a)     return (g, evtOuts, snaps ins) @@ -505,8 +503,8 @@ -----------------------------------------------------  sourceSlice :: SinkSource a -> Source a-sourceSlice = Source . (fmap (\(gui, _, a) -> (gui, a))) . unSinkSource+sourceSlice = fmap (\(gui, _, a) -> (gui, a))  sinkSlice :: SinkSource a -> Sink a-sinkSlice = Sink . (fmap (\(gui, a, _) -> (gui, a))) . unSinkSource+sinkSlice = fmap (\(gui, a, _) -> (gui, a)) 
src/Csound/Typed/Plugins.hs view
@@ -37,7 +37,7 @@     fxPanTrem, fxMonoTrem, fxPhaser, fxPitchShifter, fxReverse, fxRingModulator, fxChorus2, fxPingPong,      -- * Tape echo-    tapeRead, tapeWrite,+    tapeRead, tapeWrite, tapeEcho,      -- utilities     delay1k
src/Csound/Typed/Plugins/TapeEcho.hs view
@@ -1,6 +1,7 @@ module Csound.Typed.Plugins.TapeEcho(     tapeRead   , tapeWrite+  , tapeEcho ) where  import Control.Monad.Trans.Class@@ -12,9 +13,9 @@ import Csound.Typed.GlobalState import qualified Csound.Typed.GlobalState.Elements as E(tapeEchoPlugin) ---  Function to read from tape.+-- | Function to read from tape. -----  tapeRead aIn, kDelay, kRandomSpread+--  > tapeRead aIn, kDelay, kRandomSpread -- -- The function is used in the same manner as deltapi --  first init the delay buffer and the use tapeRead.@@ -31,9 +32,9 @@   where f ain kdel krand = opcs "tapeRead" [(Ar, [Ar, Kr, Kr])] [ain, kdel, krand]  --- function to write to tape+-- | Function to write to tape ----- tapeWrite aIn, aOut, kFbGain+-- > tapeWrite aIn, aOut, kFbGain -- -- It should be though of as delayw for magnetic tape. --@@ -45,8 +46,19 @@   f <$> toGE ain <*> toGE aout <*> toGE kFeedback   where f ain aout kfb = opcs "tapeWrite" [(Xr, [Ar, Ar, Kr])] [ain, aout, kfb] -{--addUdoPlugin E.pitchShifterDelayPlugin-    f <$> toGE ain <*> toGE ktrans <*> toGE kdlt <*> toGE kFB1 <*> toGE kFB2 <*> toGE imaxdlt-    where f ain ktrans kdlt kFB1 kFB2 imaxdlt = opcs "PitchShifterDelay" [(Ar, [Ar, Kr, Kr, Kr, Kr, Ir])] [ain, ktrans, kdlt, kFB1, kFB2, imaxdlt]--}+-- | Generic multi-tap echo opcode.+--+-- > tapeEcho iSize kDelay kEchoGain kFbGain kTone kRandomSpread aIn+--+-- * iSize - how many units of echo+-- * kDelay - delay time+-- * kEchoGain - gain of the echoes+-- * kFbGain - feedback+-- * kTone - low pass filter frequency+-- * kRandomSpread - quality of the tape [0, Inf], the higher the worser the quality of the tape.+-- * aIn - input signal+tapeEcho :: D -> Sig -> Sig -> Sig -> Sig -> Sig -> Sig -> Sig+tapeEcho iSize kDelay kEchoGain kFbGain kTone kRandomSpread aIn = fromGE $ do+  addUdoPlugin E.tapeEchoPlugin+  f <$> toGE aIn <*> toGE kDelay <*> toGE kEchoGain <*> toGE kFbGain <*> toGE kTone <*> toGE kRandomSpread <*> toGE iSize+  where f aIn kDelay kEchoGain kFbGain kTone kRandomSpread iSize = opcs "TapeEchoN" [(Ar, [Ar, Kr, Kr, Kr, Kr, Kr, Ir])] [aIn, kDelay, kEchoGain, kFbGain, kTone, kRandomSpread, iSize]
src/Csound/Typed/Types/Evt.hs view
@@ -1,4 +1,4 @@-{-# Language TypeFamilies, FlexibleContexts #-}+{-# Language TypeFamilies, FlexibleContexts, CPP #-} module Csound.Typed.Types.Evt(     Evt(..), Bam, sync,     boolToEvt, evtToBool, sigToEvt, stepper,@@ -28,9 +28,25 @@ instance Functor Evt where     fmap f a = Evt $ \bam -> runEvt a (bam . f) +instance Default (Evt a) where+    def = Evt $ const $ return ()++#if MIN_VERSION_base(4,11,0)+instance Semigroup (Evt a) where+    (<>) = mappendEvt+ instance Monoid (Evt a) where-    mempty = Evt $ const $ return ()-    mappend a b = Evt $ \bam -> runEvt a bam >> runEvt b bam+    mempty  = def++#else++instance Monoid (Evt a) where+    mempty  = def+    mappend = mappendEvt++#endif++mappendEvt a b = Evt $ \bam -> runEvt a bam >> runEvt b bam  -- | Converts booleans to events. boolToEvt :: BoolSig -> Evt Unit
src/Csound/Typed/Types/MixSco.hs view
@@ -16,46 +16,46 @@  import qualified Temporal.Media as T -type CsdEventList a = T.Track D a+type CsdEventList a = T.Track Sig a -csdEventListNotes :: CsdEventList a -> [(D, D, a)]+csdEventListNotes :: CsdEventList a -> [(Sig, Sig, a)] csdEventListNotes a = fmap (\(T.Event start dur content) -> (start, dur, content)) $ T.render a -csdEventListDur :: CsdEventList a -> D+csdEventListDur :: CsdEventList a -> Sig csdEventListDur = T.dur -rescaleCsdEventList :: D -> CsdEventList a -> CsdEventList a+rescaleCsdEventList :: Sig -> CsdEventList a -> CsdEventList a rescaleCsdEventList = T.str -delayCsdEventList :: D -> CsdEventList a -> CsdEventList a+delayCsdEventList :: Sig -> CsdEventList a -> CsdEventList a delayCsdEventList = T.del   type TupleMonoArg = (E,E,E,E) type RawMonoInstr = TupleMonoArg -> Dep [E] -data M +data M     = Snd InstrId (CsdEventList [E])     | MonoSnd { monoSndInstr :: InstrId, monoSndArgs :: InstrId, monoSndNotes :: (CsdEventList [E]) }-    | Eff InstrId (CsdEventList M) Int   +    | Eff InstrId (CsdEventList M) Int  delayAndRescaleCsdEventListM :: CsdEventList M -> CsdEventList M delayAndRescaleCsdEventListM = delayCsdEventListM . rescaleCsdEventListM  delayCsdEventListM :: CsdEventList M -> CsdEventList M-delayCsdEventListM = T.mapEvents delayCsdEventM    +delayCsdEventListM = T.mapEvents delayCsdEventM -delayCsdEventM :: T.Event D M -> T.Event D M+delayCsdEventM :: T.Event Sig M -> T.Event Sig M delayCsdEventM (T.Event start dur evt) = T.Event start dur (phi evt)     where phi x = case x of             Snd n evts                  -> Snd n $ delayCsdEventList start evts             MonoSnd instrId argId evts  -> MonoSnd instrId argId  $ delayCsdEventList start evts-            Eff n evts arityIn          -> Eff n (delayCsdEventListM $ delayCsdEventList start evts) arityIn        +            Eff n evts arityIn          -> Eff n (delayCsdEventListM $ delayCsdEventList start evts) arityIn  rescaleCsdEventListM :: CsdEventList M -> CsdEventList M-rescaleCsdEventListM = T.mapEvents rescaleCsdEventM    +rescaleCsdEventListM = T.mapEvents rescaleCsdEventM -rescaleCsdEventM :: T.Event D M -> T.Event D M+rescaleCsdEventM :: T.Event Sig M -> T.Event Sig M rescaleCsdEventM (T.Event start dur evt) = T.Event start dur (phi evt)     where phi x = case x of             Snd n evts                  -> Snd n $ rescaleCsdEventList (dur/localDur) evts@@ -68,65 +68,65 @@  renderMixSco :: Int -> CsdEventList M -> Dep [E] renderMixSco arity evts = do-    chnId <- chnRefAlloc arity  -    aliveCountRef <- unSE $ newRef (10 :: D)      -    go aliveCountRef chnId evts    +    chnId <- chnRefAlloc arity+    aliveCountRef <- unSE $ newRef (10 :: D)+    go aliveCountRef chnId evts     readChn chnId-    where +    where         go :: Ref D -> ChnRef -> CsdEventList M -> Dep ()         go aliveCountRef outId xs = do             mapM_ (onEvent aliveCountRef outId) notes             unSE $ writeRef aliveCountRef $ int $ 2 * length notes             aliveCount <- unSE $ readRef aliveCountRef-            hideGEinDep $ liftA2 masterUpdateChnAlive (return chnId) $ toGE aliveCount -            where +            hideGEinDep $ liftA2 masterUpdateChnAlive (return chnId) $ toGE aliveCount+            where                 notes = csdEventListNotes xs                 chnId = outId -        onEvent :: Ref D -> ChnRef -> (D, D, M) -> Dep ()+        onEvent :: Ref D -> ChnRef -> (Sig, Sig, M) -> Dep ()         onEvent aliveCountRef outId (start, dur, x) = case x of             Snd instrId es          -> onSnd aliveCountRef instrId outId es-            MonoSnd instr arg es    -> onMonoSnd instr arg start dur outId es +            MonoSnd instr arg es    -> onMonoSnd instr arg start dur outId es             Eff instrId es arityIn  -> onEff aliveCountRef instrId start dur outId es arityIn -        onSnd _ instrId outId es = forM_ (csdEventListNotes es) $ \(start, dur, args) -> +        onSnd _ instrId outId es = forM_ (csdEventListNotes es) $ \(start, dur, args) ->             mkEvent instrId start dur (args ++ [chnRefId outId])          onEff aliveCountRef instrId start dur outId es arityIn = do             inId <- chnRefAlloc arityIn-            mkEvent instrId start dur [chnRefId inId, chnRefId outId]            +            mkEvent instrId start dur [chnRefId inId, chnRefId outId]             go aliveCountRef inId es          onMonoSnd instrId argId start dur outId es = do             inId <- chnRefAlloc arityMonoIn -            forM_ (csdEventListNotes es) $ \(startLocal, durLocal, args) -> +            forM_ (csdEventListNotes es) $ \(startLocal, durLocal, args) ->                 mkEvent argId startLocal durLocal (args ++ [chnRefId inId])-            +             mkEvent instrId start dur [chnRefId inId, chnRefId outId]-            where arityMonoIn = 3 +            where arityMonoIn = 3   renderMixSco_ :: CsdEventList M -> Dep () renderMixSco_ evts = mapM_ onEvent $ csdEventListNotes evts     where-        onEvent :: (D, D, M) -> Dep ()+        onEvent :: (Sig, Sig, M) -> Dep ()         onEvent (start, dur, x) = case x of             Snd instrId es       -> onSnd instrId es             MonoSnd instr arg es -> onMonoSnd instr arg es             Eff instrId es _     -> onEff instrId start dur es -        onSnd instrId es = forM_ (csdEventListNotes es) $ \(start, dur, args) -> +        onSnd instrId es = forM_ (csdEventListNotes es) $ \(start, dur, args) ->             mkEvent instrId start dur args          onEff instrId start dur es = do-            mkEvent instrId start dur [] +            mkEvent instrId start dur []             renderMixSco_ es          onMonoSnd instr arg es = undefined  -mkEvent :: InstrId -> D -> D -> [E] -> Dep ()+mkEvent :: InstrId -> Sig -> Sig -> [E] -> Dep () mkEvent instrId startD durD args =  hideGEinDep $ do         start <- toGE startD         dur   <- toGE durD
src/Csound/Typed/Types/Prim.hs view
@@ -1,4 +1,4 @@-{-# Language TypeFamilies, FlexibleInstances, FlexibleContexts, ScopedTypeVariables, Rank2Types #-}+{-# Language TypeFamilies, FlexibleInstances, FlexibleContexts, ScopedTypeVariables, Rank2Types, CPP #-} module Csound.Typed.Types.Prim(     Sig(..), unSig, D(..), unD, Tab(..), unTab, Str(..), Spec(..), Wspec(..), renderTab,     BoolSig(..), unBoolSig, BoolD(..), unBoolD, Unit(..), unit, Val(..), hideGE, SigOrD,@@ -17,6 +17,7 @@      -- ** constants     idur, getSampleRate, getControlRate, getBlockSize, getZeroDbfs,+    getBpm, setBpm,      -- ** converters     ar, kr, ir, sig,@@ -50,6 +51,7 @@  import Data.Default import Data.Boolean+import Data.String  import Csound.Dynamic hiding (double, int, str, when1, whens, ifBegin, ifEnd, elseBegin, untilBegin, untilEnd, untilDo, whileBegin, whileEnd, whileDo) import qualified Csound.Dynamic as D(double, int, str, ifBegin, ifEnd, elseBegin, untilBegin, untilEnd, whileBegin, whileEnd)@@ -139,10 +141,24 @@ unit :: Unit unit = Unit $ return () +#if MIN_VERSION_base(4,11,0)+instance Semigroup Unit where+    (<>) = mappendUnit+ instance Monoid Unit where-    mempty = Unit (return ())-    mappend a b = Unit $ (unUnit a) >> (unUnit b)+    mempty  = def +#else++instance Monoid Unit where+    mempty  = def+    mappend = mappendUnit++#endif++mappendUnit :: Unit -> Unit -> Unit+mappendUnit a b = Unit $ (unUnit a) >> (unUnit b)+ instance Default Unit where     def = unit @@ -298,6 +314,9 @@ text :: String -> Str text = fromE . D.str +instance IsString Str where+    fromString = text+ ------------------------------------------------------------------------------- -- constants @@ -317,24 +336,40 @@ getZeroDbfs :: D getZeroDbfs = fromE $ readOnlyVar (VarVerbatim Ir "0dbfs") +-- | Gets the global BPM value.+getBpm :: Sig+getBpm = fromE $ readOnlyVar bpmVar++-- | Sets the global BPM value.+setBpm :: Sig -> SE ()+setBpm x = fromDep_ $ hideGEinDep $ fmap (writeVar bpmVar) (toGE x)+ ------------------------------------------------------------------------------- -- converters  -- | Sets a rate of the signal to audio rate. ar :: Sig -> Sig-ar = on1 $ setRate Ar+ar x = case x of+    PrimSig a -> PrimSig a+    Sig exp   -> Sig $ fmap (setRate Ar) exp  -- | Sets a rate of the signal to control rate. kr :: Sig -> Sig-kr = on1 $ setRate Kr+kr x = case x of+    PrimSig a -> PrimSig a+    Sig exp   -> Sig $ fmap (setRate Kr) exp  -- | Converts a signal to the number (initial value of the signal). ir :: Sig -> D-ir = on1 $ setRate Ir+ir x = case x of+    PrimSig a -> PrimD a+    Sig a -> D $ fmap (setRate Ir) a  -- | Makes a constant signal from the number. sig :: D -> Sig-sig = on1 $ setRate Kr+sig x = case x of+    PrimD a -> PrimSig a+    D exp   -> Sig $ fmap (setRate Kr) exp  ------------------------------------------------------------------------------- -- single wrapper@@ -435,8 +470,36 @@ ------------------------------------------------------------------------------- -- monoid -instance Monoid Sig     where { mempty = on0 mempty     ; mappend = on2 mappend }-instance Monoid D       where { mempty = on0 mempty     ; mappend = on2 mappend }+#if MIN_VERSION_base(4,11,0)+instance Semigroup Sig where+    (<>) = on2 mappend++instance Monoid Sig where+    mempty = on0 mempty++#else++instance Monoid Sig where+    mempty  = on0 mempty+    mappend = on2 mappend++#endif+++#if MIN_VERSION_base(4,11,0)+instance Semigroup D where+    (<>) = on2 mappend++instance Monoid D where+    mempty = on0 mempty++#else++instance Monoid D where+    mempty  = on0 mempty+    mappend = on2 mappend++#endif  ------------------------------------------------------------------------------- -- numeric
src/Csound/Typed/Types/SigSpace.hs view
@@ -3,7 +3,8 @@         TypeFamilies,         MultiParamTypeClasses,         FlexibleInstances,-        FlexibleContexts #-}+        FlexibleContexts,+        CPP #-} module Csound.Typed.Types.SigSpace(     SigSpace(..), BindSig(..), mul, mul', on, uon, At(..), MixAt(..),     cfd, genCfds, cfd4, cfds,@@ -105,6 +106,7 @@ instance SigSpace Sig   where  mapSig = id instance BindSig  Sig   where  bindSig = id +#if __GLASGOW_HASKELL__ >= 710 instance (SigSpace a1, SigSpace a2) => SigSpace (a1, a2) where  mapSig  f (a1, a2) = (mapSig f a1, mapSig f a2) instance (BindSig a1, BindSig a2) => BindSig  (a1, a2) where  bindSig f (a1, a2) = (,) <$> bindSig f a1 <*> bindSig f a2 @@ -126,8 +128,57 @@ instance (SigSpace a1, SigSpace a2, SigSpace a3, SigSpace a4, SigSpace a5, SigSpace a6, SigSpace a7, SigSpace a8) => SigSpace (a1, a2, a3, a4, a5, a6, a7, a8) where mapSig  f (a1, a2, a3, a4, a5, a6, a7, a8) = (mapSig f a1, mapSig f a2, mapSig f a3, mapSig f a4, mapSig f a5, mapSig f a6, mapSig f a7, mapSig f a8) instance (BindSig a1, BindSig a2, BindSig a3, BindSig a4, BindSig a5, BindSig a6, BindSig a7, BindSig a8) => BindSig  (a1, a2, a3, a4, a5, a6, a7, a8) where bindSig f (a1, a2, a3, a4, a5, a6, a7, a8) = (,,,,,,,) <$> bindSig f a1 <*> bindSig f a2 <*> bindSig f a3 <*> bindSig f a4 <*> bindSig f a5 <*> bindSig f a6 <*> bindSig f a7 <*> bindSig f a8 -instance SigSpace a => SigSpace (SE a) where  mapSig  f = fmap (mapSig f)-instance BindSig  a => BindSig  (SE a) where  bindSig f = fmap (bindSig f)+instance {-# OVERLAPPABLE #-} SigSpace a => SigSpace (SE a) where  mapSig  f = fmap (mapSig f)+instance {-# OVERLAPPABLE #-} BindSig a  => BindSig  (SE a) where  bindSig f = fmap (bindSig f)+#endif++#if __GLASGOW_HASKELL__ < 710++instance SigSpace (Sig, Sig) where  mapSig  f (a1, a2) = (mapSig f a1, mapSig f a2)+instance BindSig  (Sig, Sig) where  bindSig f (a1, a2) = (,) <$> bindSig f a1 <*> bindSig f a2++instance SigSpace (Sig, Sig, Sig) where mapSig  f (a1, a2, a3) = (mapSig f a1, mapSig f a2, mapSig f a3)+instance BindSig  (Sig, Sig, Sig) where bindSig f (a1, a2, a3) = (,,) <$> bindSig f a1 <*> bindSig f a2 <*> bindSig f a3++instance SigSpace (Sig, Sig, Sig, Sig) where mapSig  f (a1, a2, a3, a4) = (mapSig f a1, mapSig f a2, mapSig f a3, mapSig f a4)+instance BindSig  (Sig, Sig, Sig, Sig) where bindSig f (a1, a2, a3, a4) = (,,,) <$> bindSig f a1 <*> bindSig f a2 <*> bindSig f a3 <*> bindSig f a4++instance SigSpace (Sig, Sig, Sig, Sig, Sig) where mapSig  f (a1, a2, a3, a4, a5) = (mapSig f a1, mapSig f a2, mapSig f a3, mapSig f a4, mapSig f a5)+instance BindSig  (Sig, Sig, Sig, Sig, Sig) where bindSig f (a1, a2, a3, a4, a5) = (,,,,) <$> bindSig f a1 <*> bindSig f a2 <*> bindSig f a3 <*> bindSig f a4 <*> bindSig f a5++instance SigSpace (Sig, Sig, Sig, Sig, Sig, Sig) where mapSig  f (a1, a2, a3, a4, a5, a6) = (mapSig f a1, mapSig f a2, mapSig f a3, mapSig f a4, mapSig f a5, mapSig f a6)+instance BindSig  (Sig, Sig, Sig, Sig, Sig, Sig) where bindSig f (a1, a2, a3, a4, a5, a6) = (,,,,,) <$> bindSig f a1 <*> bindSig f a2 <*> bindSig f a3 <*> bindSig f a4 <*> bindSig f a5 <*> bindSig f a6++instance SigSpace (Sig, Sig, Sig, Sig, Sig, Sig, Sig) where mapSig  f (a1, a2, a3, a4, a5, a6, a7) = (mapSig f a1, mapSig f a2, mapSig f a3, mapSig f a4, mapSig f a5, mapSig f a6, mapSig f a7)+instance BindSig  (Sig, Sig, Sig, Sig, Sig, Sig, Sig) where bindSig f (a1, a2, a3, a4, a5, a6, a7) = (,,,,,,) <$> bindSig f a1 <*> bindSig f a2 <*> bindSig f a3 <*> bindSig f a4 <*> bindSig f a5 <*> bindSig f a6 <*> bindSig f a7++instance SigSpace (Sig, Sig, Sig, Sig, Sig, Sig, Sig, Sig) where mapSig  f (a1, a2, a3, a4, a5, a6, a7, a8) = (mapSig f a1, mapSig f a2, mapSig f a3, mapSig f a4, mapSig f a5, mapSig f a6, mapSig f a7, mapSig f a8)+instance BindSig  (Sig, Sig, Sig, Sig, Sig, Sig, Sig, Sig) where bindSig f (a1, a2, a3, a4, a5, a6, a7, a8) = (,,,,,,,) <$> bindSig f a1 <*> bindSig f a2 <*> bindSig f a3 <*> bindSig f a4 <*> bindSig f a5 <*> bindSig f a6 <*> bindSig f a7 <*> bindSig f a8++instance SigSpace (SE Sig) where  mapSig  f = fmap (mapSig f)+instance BindSig  (SE Sig) where  bindSig f = fmap (bindSig f)++instance SigSpace (SE (Sig, Sig)) where  mapSig  f = fmap (mapSig f)+instance BindSig  (SE (Sig, Sig)) where  bindSig f = fmap (bindSig f)++instance SigSpace (SE (Sig, Sig, Sig)) where  mapSig  f = fmap (mapSig f)+instance BindSig  (SE (Sig, Sig, Sig)) where  bindSig f = fmap (bindSig f)++instance SigSpace (SE (Sig, Sig, Sig, Sig)) where  mapSig  f = fmap (mapSig f)+instance BindSig  (SE (Sig, Sig, Sig, Sig)) where  bindSig f = fmap (bindSig f)++instance SigSpace (SE (Sig, Sig, Sig, Sig, Sig)) where  mapSig  f = fmap (mapSig f)+instance BindSig  (SE (Sig, Sig, Sig, Sig, Sig)) where  bindSig f = fmap (bindSig f)++instance SigSpace (SE (Sig, Sig, Sig, Sig, Sig, Sig)) where  mapSig  f = fmap (mapSig f)+instance BindSig  (SE (Sig, Sig, Sig, Sig, Sig, Sig)) where  bindSig f = fmap (bindSig f)++instance SigSpace (SE (Sig, Sig, Sig, Sig, Sig, Sig, Sig)) where  mapSig  f = fmap (mapSig f)+instance BindSig  (SE (Sig, Sig, Sig, Sig, Sig, Sig, Sig)) where  bindSig f = fmap (bindSig f)++instance SigSpace (SE (Sig, Sig, Sig, Sig, Sig, Sig, Sig, Sig)) where  mapSig  f = fmap (mapSig f)+instance BindSig  (SE (Sig, Sig, Sig, Sig, Sig, Sig, Sig, Sig)) where  bindSig f = fmap (bindSig f)+#endif  ---------------------------------------------------------------------------------------------------------- 
src/Csound/Typed/Types/Tuple.hs view
@@ -2,7 +2,8 @@ {-# Language         TypeFamilies,         FlexibleContexts,-        FlexibleInstances #-}+        FlexibleInstances,+        CPP #-} module Csound.Typed.Types.Tuple(     -- ** Tuple     Tuple(..), TupleMethods, makeTupleMethods,@@ -154,6 +155,8 @@ class (Sigs a, SigSpace2 a, BindSig2 a) => Sig2s a where  instance Sigs Sig++#if __GLASGOW_HASKELL__ >= 710 instance (Sigs a1, Sigs a2) => Sigs (a1, a2) instance (Sigs a1, Sigs a2, Sigs a3) => Sigs (a1, a2, a3) instance (Sigs a1, Sigs a2, Sigs a3, Sigs a4) => Sigs (a1, a2, a3, a4)@@ -161,6 +164,15 @@ instance (Sigs a1, Sigs a2, Sigs a3, Sigs a4, Sigs a5, Sigs a6) => Sigs (a1, a2, a3, a4, a5, a6) instance (Sigs a1, Sigs a2, Sigs a3, Sigs a4, Sigs a5, Sigs a6, Sigs a7) => Sigs (a1, a2, a3, a4, a5, a6, a7) instance (Sigs a1, Sigs a2, Sigs a3, Sigs a4, Sigs a5, Sigs a6, Sigs a7, Sigs a8) => Sigs (a1, a2, a3, a4, a5, a6, a7, a8)+#else+instance Sigs (Sig, Sig)+instance Sigs (Sig, Sig, Sig)+instance Sigs (Sig, Sig, Sig, Sig)+instance Sigs (Sig, Sig, Sig, Sig, Sig)+instance Sigs (Sig, Sig, Sig, Sig, Sig, Sig)+instance Sigs (Sig, Sig, Sig, Sig, Sig, Sig, Sig)+instance Sigs (Sig, Sig, Sig, Sig, Sig, Sig, Sig, Sig)+#endif  instance Sig2s Sig instance Sig2s Sig2