packages feed

haskore-supercollider 0.0.2 → 0.1

raw patch · 18 files changed

+385/−131 lines, 18 filesdep +containersdep +opensoundcontrol-htdep +transformersdep −mtldep ~arraydep ~data-accessordep ~haskore

Dependencies added: containers, opensoundcontrol-ht, transformers, utility-ht

Dependencies removed: mtl

Dependency ranges changed: array, data-accessor, haskore, haskore-realtime, hosc, hsc3, random, supercollider-ht

Files

Makefile view
@@ -1,7 +1,7 @@ .PHONY:	ghci jack jack-rt supercollider supercollider-rt scj  ghci:-	ghci -i:src+	ghci -i:src src/Haskore/Interface/SuperCollider/Example.hs  jack: # -n 2 is default, larger values are not supported
haskore-supercollider.cabal view
@@ -1,11 +1,10 @@ Name:           haskore-supercollider-Version:        0.0.2+Version:        0.1 License:        GPL License-File:   LICENSE Author:         Henning Thielemann <haskell@henning-thielemann.de> Homepage:       http://www.haskell.org/haskellwiki/SuperCollider-Package-URL:    http://darcs.haskell.org/haskore-supercollider/-Category:       Sound+Category:       Sound, Music Synopsis:       Haskore back-end for SuperCollider Description:   This package lets you play Haskore music via Supercollider@@ -14,13 +13,21 @@   We support realtime replay and rendering to disk. Stability:      Experimental Tested-With:    GHC==6.4.1, GHC==6.8.2-Cabal-Version:  >=1.2+Cabal-Version:  >=1.6 Build-Type:     Simple- Extra-Source-Files:   Makefile   Readme +Source-Repository head+  type:     darcs+  location: http://darcs.haskell.org/haskore-supercollider/++Source-Repository this+  type:     darcs+  location: http://darcs.haskell.org/haskore-supercollider/+  tag:      0.1+ Flag splitBase   description: Choose the new smaller, split-up base package. @@ -30,21 +37,27 @@  Library   Build-Depends:-    haskore-realtime >= 0.0.2 && < 0.1,-    haskore >=0.0.5 && <0.1,+    haskore-realtime >= 0.1 && < 0.2,+    haskore >=0.1 && <0.2,     -- for SuperCollider support-    hosc >=0.1 && <0.2, hsc3 >=0.1 && <0.2, supercollider-ht >=0.0 && <0.1,+    hosc >=0.6 && <0.7, hsc3 >=0.6 && <0.7,+    opensoundcontrol-ht >=0.1 && <0.2, supercollider-ht >=0.1 && <0.2,     bytestring >=0.9 && <1.0,     -- dependency on non-negative for Haddock     non-negative >=0.0.1 && <0.1,     event-list >=0.0.6 && <0.1,-    data-accessor >=0.1 && <0.2,+    data-accessor >=0.2 && <0.3,+    utility-ht >=0.0.3 && <0.1,     unix >= 2.0 && <3,-    mtl >=1.0 && <2+    transformers >=0.0 && <0.2    If flag(splitBase)     Build-Depends:-      base >= 3, random >= 1.0 && < 1.1, array >= 0.1 && < 1, process >= 1.0 && < 1.1+      base >= 3,+      array >= 0.1 && <1.0,+      containers >=0.1 && <1.0,+      random >= 1.0 && <2.0,+      process >= 1.0 && <1.1   Else     Build-Depends:       base >= 1.0 && < 2@@ -71,6 +84,11 @@     Haskore.Interface.SuperCollider.Schedule.Install,     Haskore.Interface.SuperCollider.Schedule.Channel   Other-modules:+    Haskore.Interface.SuperCollider.Timer,+    Haskore.General.IdGenerator,+    Haskore.General.IdGenerator.Modulo,+    Haskore.General.IdGenerator.Set,+    Haskore.General.IdGenerator.Simple,     Haskore.Interface.SuperCollider.Example.Air,     Haskore.Interface.SuperCollider.Example.Morph 
+ src/Haskore/General/IdGenerator.hs view
@@ -0,0 +1,85 @@+{- | Identifier generator++Generates unique elements but elements can be declared as unused, again.++-}++module Haskore.General.IdGenerator where++import Data.Set (Set)+import qualified Data.Set as Set+import Control.Monad.Trans.State(State, state, evalState, modify, get, )+import Control.Monad (when, )+import Data.Tuple.HT (mapFst, )++{- |++The generator is a state monad+where the state consists of the set of the explicitly unused elements+and a lower bound for another set of ids that are still unused.+Essentially, the Set stores all recycled ids,+and the lower bound stores the ids not used so far.+All elements in the explicit set must be below the bound.++-}++type T i a = State (St i) a++type St i = (Set i, i)++run :: i -> T i a -> a+run start gen = evalState gen (Set.empty, start)++{- |++Reserve a new id.++-}++alloc :: (Ord i, Enum i) => T i i+alloc =+   state $ \(set, next) ->+      if Set.null set+        then (next, (set, succ next))+        else let (newId, newSet) = Set.deleteFindMin set+             in  (newId, (newSet, next))++{- |++Return an id.++We call reduce in order to prevent the set from growing too much.+We call it only once in order to prevent a heavy CPU lead+when the last id of a sequence is returned.+So the reduction is spread over several calls to 'free'.++-}++free :: (Ord i, Enum i) => i -> T i ()+free oldId =+   do s <- get+      when (isFree s oldId)+           (error "IdGenerator.free: id freed twice")+      modify (mapFst (Set.insert oldId))+      modify reduce++{- |++If the largest free id and the lower bound of free ids are successive elements+then we can decrease the lower bound.+This procedure can be iterated.+This way we can save storage in the set.++-}++reduce :: (Ord i, Enum i) => St i -> St i+reduce (set, next) =+   if not (Set.null set) && Set.findMax set == pred next+     then (Set.deleteMax set, pred next)+     else (set, next)++isFree :: (Ord i) => St i -> i -> Bool+isFree (set,next) i = Set.member i set || i >= next++isValid :: (Ord i) => St i -> Bool+isValid (set,next) = Set.findMax set < next
+ src/Haskore/General/IdGenerator/Modulo.hs view
@@ -0,0 +1,43 @@+{- | Identifier generator++A simple test of whether identifiers can be re-used in SuperCollider.+This has no practical use.++-}++module Haskore.General.IdGenerator.Modulo where++import Control.Monad.Trans.State (State, evalState, modify, get, )++{- |++The generator is a simple state monad.++-}++type T i a = State i a++run :: i -> T i a -> a+run = flip evalState++{- |++Reserve a new id.++-}++alloc :: (Integral i) => T i i+alloc =+   do newId <- get+      modify (flip mod 50 . succ)+      return (newId+2)++{- |++Unreserve an id.+In this implementation it performs essentially nothing.++-}++free :: i -> T i ()+free _ = return ()
+ src/Haskore/General/IdGenerator/Set.hs view
@@ -0,0 +1,52 @@+{- | Identifier generator++Generates unique elements but elements can be declared as unused, again.++-}++module Haskore.General.IdGenerator.Set where++import Data.Set (Set)+import qualified Data.Set as Set+import Control.Monad.Trans.RWS(RWS, evalRWS, modify, get, ask, )+import Control.Monad (when, )++{- |++The generator is a reader+state monad+where the state consists of the allocated identifiers+and the reader source is the least element ever used.++-}++type T i a = RWS i () (Set i) a++run :: i -> T i a -> a+run start gen = fst $ evalRWS gen start Set.empty++{- |++Reserve a new id.++-}++alloc :: (Ord i, Enum i) => T i i+alloc =+   do start <- ask+      allocated <- get+      let newId = head $ filter (not . flip Set.member allocated) [start ..]+      modify (Set.insert newId)+      return newId++{- |++Deallocate an id.++-}++free :: (Ord i, Enum i) => i -> T i ()+free oldId =+   do allocated <- get+      when (not $ Set.member oldId allocated)+           (error "IdGeneratorSet.free: deallocated free identifier")+      modify (Set.delete oldId)
+ src/Haskore/General/IdGenerator/Simple.hs view
@@ -0,0 +1,46 @@+{- | Identifier generator++Generates unique elements without recycling of identifiers.++-}++module Haskore.General.IdGenerator.Simple where++import Control.Monad.Trans.State (State, evalState, modify, get, )+import Control.Monad (when, )++{- |++The generator is a simple state monad.++-}++type T i a = State i a++run :: i -> T i a -> a+run = flip evalState++{- |++Reserve a new id.++-}++alloc :: (Enum i) => T i i+alloc =+   do newId <- get+      modify succ+      return newId++{- |++Unreserve an id.+In this implementation it performs essentially nothing.++-}++free :: (Ord i) => i -> T i ()+free oldId =+   do freeId <- get+      when (freeId <= oldId)+           (error "IdGeneratorSimple.free: freed unreserved id")
src/Haskore/Interface/SuperCollider/Channel/State.hs view
@@ -4,8 +4,8 @@ -} module Haskore.Interface.SuperCollider.Channel.State where -import qualified Control.Monad.State as State-import Control.Monad.State (StateT)+import qualified Control.Monad.Trans.State as State+import Control.Monad.Trans.State (StateT)  import qualified Haskore.Interface.SuperCollider.Channel as ChannelMng import Haskore.Interface.SuperCollider.Channel
src/Haskore/Interface/SuperCollider/Note.hs view
@@ -12,9 +12,11 @@  import qualified Numeric.NonNegative.Wrapper as NonNeg -import Haskore.General.Utility-          (compareRecord, compareField, equalRecord, equalField)+import qualified Data.Record.HT as Record+import Data.Ord.HT (comparing, )+import Data.Eq.HT  (equating, ) + data T =    Cons {      parameters  :: [Attribute],@@ -32,15 +34,15 @@  instance Eq T where    (==) =-      equalRecord-         [equalField pitch,-          equalField velocity]+      Record.equal+         [equating pitch,+          equating velocity]  instance Ord T where    compare =-      compareRecord-         [compareField pitch,-          compareField velocity]+      Record.compare+         [comparing pitch,+          comparing velocity]  type FromNote dyn note =         dyn -> Pitch.Relative -> note -> T
src/Haskore/Interface/SuperCollider/Play.hs view
@@ -25,23 +25,23 @@  -- import Sound.SC3.UGen.UGen (UGen) -import Sound.OpenSoundControl.Transport (Transport) import qualified Sound.OpenSoundControl.Transport.Monad as Trans--- import qualified Sound.OpenSoundControl.Transport.UDP      as UDP--- import qualified Sound.OpenSoundControl.UDPMonad as UDP-import Sound.OpenSoundControl.OSC (OSC)+import Sound.OpenSoundControl.OSC (OSC(Bundle))+import qualified Sound.OpenSoundControl.Time as OSCTime + import qualified Haskore.Melody            as Melody -- import qualified Haskore.Music.Rhythmic    as RhyMusic import qualified Haskore.Music             as Music -import qualified Haskore.RealTime.EventList.TimeBody    as TimeList+import qualified Haskore.Interface.SuperCollider.Timer as SCTimer+import qualified Haskore.RealTime.Timer                as Timer+import qualified Haskore.RealTime.EventList.TimeBody   as TimeList -import qualified Haskore.RealTime.Timer           as Timer-import qualified Haskore.RealTime.Timer.Thread    as TimerThread+import qualified Numeric.NonNegative.Wrapper as NonNeg --- import Control.Monad.Trans (liftIO)--- import Control.Monad (when)+import Control.Monad.Trans (MonadIO, )+import Control.Monad (liftM, )   @@ -83,14 +83,14 @@    Schedule.fromMelody sound  -performanceTrans :: Transport t =>+performanceTrans :: (Trans.C m, MonadIO m) =>    Time ->    [OSC] ->    SCPf.T Time ->-   Trans.IO t ()+   m () performanceTrans latency installMsgs =    scheduleWithPlayer-      (messagesGrouped TimerThread.timer latency) .+      (messagesGrouped SCTimer.timer latency) .    Schedule.fromPerformance installMsgs []  performance ::@@ -110,7 +110,7 @@ schedule latency =    SCPlay.withSC3 .    scheduleWithPlayer-      (messagesGrouped TimerThread.timer latency)+      (messagesGrouped SCTimer.timer latency)   shutUp :: IO ()@@ -131,23 +131,23 @@  -- should be moved to Hsc or supercollider-ht timeStamp :: Time -> Time -> [OSC] -> OSC-timeStamp start t = Schedule.timeStamp (start+t)+timeStamp start t = Bundle $ OSCTime.UTCr $ NonNeg.toNumber (start+t)   installSound ::-   (Transport t, SoundMap.SoundParameters params) =>+   (Trans.C m, SoundMap.SoundParameters params) =>    String ->    Sound params ->-   Trans.IO t ()+   m () installSound name instr =    SCPlay.simpleSync $ Schedule.installSoundMsg name Schedule.defaultChannel instr  -playAtom :: Transport t =>+playAtom :: Trans.C m =>       SCPlay.NodeId    -> String    -> [(String,Double)]-   -> Trans.IO t ()+   -> m () playAtom sid name params =    Trans.send (Schedule.atomPlayMsg sid name params) @@ -186,10 +186,10 @@  -} -scheduleWithPlayer :: Transport t =>-   (TimeList.T Time OSC -> Trans.IO t ()) ->+scheduleWithPlayer :: Trans.C m =>+   (TimeList.T Time OSC -> m ()) ->    Schedule.T ->-   Trans.IO t ()+   m () scheduleWithPlayer player sc =    do {- both variants do only work,          if only synchronous commands are contained -}@@ -218,12 +218,12 @@ that is, the maximal expected delay of creating and sending messages to the SuperCollider server. -}-messagesGrouped :: Transport t =>-   Timer.T ->+messagesGrouped :: (Trans.C m) =>+   Timer.T m ->    Time ->-   TimeList.T Time OSC -> Trans.IO t ()+   TimeList.T Time OSC -> m () messagesGrouped timer latency =-   fmap (const ()) .+   liftM (const ()) .    TimeList.runTimeStampGrouped timer       (\time -> Trans.send . timeStamp latency time) {-@@ -237,12 +237,12 @@ This results in splitted events which actually should occur at the same time. This makes SuperCollider switching the order messages in certain occasions. -}-messagesGroupedManual :: Transport t =>-   Timer.T ->+messagesGroupedManual :: (Trans.C m) =>+   Timer.T m ->    Time ->-   TimeList.T Time OSC -> Trans.IO t ()+   TimeList.T Time OSC -> m () messagesGroupedManual timer latency =-   fmap (const ()) .+   liftM (const ()) .    -- (\ pf -> liftIO Timer.getTimeSeconds >>= \startTime ->    TimeList.runTimeStamp timer       (\time ->@@ -258,22 +258,22 @@          (Trans.send . timeStamp latency time)) -- pf)      . TimeList.collectCoincident -messagesSingly :: Transport t =>-   Timer.T ->+messagesSingly :: (Trans.C m) =>+   Timer.T m ->    Time ->-   TimeList.T Time OSC -> Trans.IO t ()+   TimeList.T Time OSC -> m () messagesSingly timer latency =-   fmap (const ()) .+   liftM (const ()) .    TimeList.runTimeStamp timer       (\time ->          -- (liftIO $ print $ eventToMark e) >>          (Trans.send . timeStamp latency time . (:[])))  -messagesSimple :: Transport t =>-   Timer.T ->+messagesSimple :: (Trans.C m) =>+   Timer.T m ->    TimeList.T Time OSC ->-   Trans.IO t ()+   m () messagesSimple timer =-   fmap (const ()) .+   liftM (const ()) .    TimeList.run timer Trans.send
src/Haskore/Interface/SuperCollider/Play/Channel.hs view
@@ -20,8 +20,7 @@  import Sound.OpenSoundControl.Transport (Transport) import Sound.OpenSoundControl.Transport.UDP  (UDP)-import Sound.OpenSoundControl.Transport.File (File)-import qualified Sound.OpenSoundControl.Transport.Monad as Trans+import qualified Sound.OpenSoundControl.Transport.File  as File  import qualified Haskore.Interface.SuperCollider.Channel.State as ChannelState import qualified Haskore.Interface.SuperCollider.Channel as Channel@@ -45,14 +44,15 @@ import           Haskore.Music.Rhythmic (qn) import           Haskore.Melody         as Melody -import qualified Haskore.RealTime.Timer.Thread    as TimerThread--- import qualified Haskore.RealTime.Timer.Immediate as TimerImmediate+import qualified Haskore.Interface.SuperCollider.Timer as SCTimer  import qualified Haskore.General.IdGenerator      as IdGen -import qualified Control.Monad.State as State-import Control.Monad.State  (StateT, evalStateT, lift, liftM2)-import Control.Monad.Reader (ReaderT)+import qualified Control.Monad.Trans.State as State+import Control.Monad.Trans.State  (StateT, evalStateT, )+import Control.Monad.Trans.Reader (ReaderT, )+import Control.Monad.Trans (lift, )+import Control.Monad (liftM2, )   @@ -122,7 +122,7 @@              always adds new nodes to the head.              This way, the effect is run after the instrument nodes. -}           Play.scheduleWithPlayer-             (Play.messagesGrouped TimerThread.timer Play.defaultLatency)+             (Play.messagesGrouped SCTimer.timer Play.defaultLatency)              (Schedule.fromPerformance                 [Schedule.installUGenMsg effectsName                     Schedule.defaultChannel effect]@@ -135,7 +135,7 @@ run act =    SCPlay.withSC3 (evalStateT act Channel.least) -writeScript :: FilePath -> Environment File a -> IO a+writeScript :: FilePath -> Environment File.T a -> IO a writeScript fn act =    SCPlay.withSC3File fn (evalStateT act Channel.least) 
src/Haskore/Interface/SuperCollider/Play/Install.hs view
@@ -16,7 +16,6 @@  import Sound.SC3.UGen.UGen (UGen) -import Sound.OpenSoundControl.Transport (Transport) import qualified Sound.OpenSoundControl.Transport.Monad as Trans  import Haskore.Interface.SuperCollider.Schedule.Install@@ -37,48 +36,49 @@ import qualified Haskore.Music          as Music import           Haskore.Melody         as Melody +import Control.Monad.Trans (MonadIO, )   installSound ::-   (Transport t, SoundMap.SoundParameters params) =>+   (Trans.C m, SoundMap.SoundParameters params) =>    (parameterTuple -> AttributeList, graph -> SoundMap.Sound params) ->    String ->    graph ->-   Trans.IO t (Sound params parameterTuple)+   m (Sound params parameterTuple) installSound (makeAttributeList, makeSoundUGen) name instr =    Play.installSound name (makeSoundUGen instr) >>    return (Sound name makeAttributeList)   installSound0 ::-   (Transport t, SoundMap.SoundParameters params) =>+   (Trans.C m, SoundMap.SoundParameters params) =>    String ->    SoundMap.Sound params ->-   Trans.IO t (Sound params ())+   m (Sound params ()) installSound0 =    installSound SoundMap.with0Attributes  installSound1 ::-   (Transport t, SoundMap.SoundParameters params) =>+   (Trans.C m, SoundMap.SoundParameters params) =>    String ->    (UGen -> SoundMap.Sound params) ->-   Trans.IO t (Sound params Double)+   m (Sound params Double) installSound1 =    installSound SoundMap.with1Attribute  installSound2 ::-   (Transport t, SoundMap.SoundParameters params) =>+   (Trans.C m, SoundMap.SoundParameters params) =>    String ->    (UGen -> UGen -> SoundMap.Sound params) ->-   Trans.IO t (Sound params (Double,Double))+   m (Sound params (Double,Double)) installSound2 =    installSound SoundMap.with2Attributes    -playMusic :: Transport t =>-   RhyMusic.T DrumAttributes InstrumentAttributes -> Trans.IO t ()+playMusic :: (Trans.C m, MonadIO m) =>+   RhyMusic.T DrumAttributes InstrumentAttributes -> m () playMusic =    Play.performanceTrans Play.defaultLatency [] .    SCPf.fixNodeIds .
src/Haskore/Interface/SuperCollider/Play/Life.hs view
@@ -59,7 +59,7 @@ import qualified Haskore.Basic.Duration as Dur import           Haskore.Basic.Duration ((%+)) -import qualified Haskore.RealTime.Timer.Thread    as TimerThread+import qualified Haskore.Interface.SuperCollider.Timer as SCTimer  import qualified Haskore.General.IdGenerator      as IdGen @@ -152,7 +152,7 @@       let numChan = SCPlay.mceDegree ugen       chan <- Channel.next ChannelEnv.manager numChan       SCPlay.withSC3 $-         SCPlay.simpleSync $ SCPlay.d_recv' name $+         SCPlay.simpleSync $ SCPlay.d_recv_synthdef name $          SCIO.out (SCUGen.Constant (fromIntegral chan)) ugen       return (chan, numChan) @@ -226,7 +226,7 @@              always adds new nodes to the head.              This way, the effect is run after the instrument nodes. -}           Play.scheduleWithPlayer-             (Play.messagesGrouped TimerThread.timer Play.defaultLatency)+             (Play.messagesGrouped SCTimer.timer Play.defaultLatency)              (Schedule.fromPerformance                 [Schedule.installUGenMsg effectsName                     Schedule.defaultChannel effect]@@ -268,14 +268,14 @@ -} playKeyboard :: ISched.Instrument () -> IO () playKeyboard instr =-   let recurse =+   let recourse =           do char <- getChar              if char == '\004'                then putStrLn ""                else do putChar '\008'                        playKey instr char-                       recurse-   in  recurse+                       recourse+   in  recourse   
src/Haskore/Interface/SuperCollider/Render.hs view
@@ -8,6 +8,7 @@ import qualified Haskore.Interface.SuperCollider.Schedule as Schedule import qualified Haskore.Interface.SuperCollider.Play     as Play +import Haskore.Interface.SuperCollider.Schedule (Time) import Haskore.Interface.SuperCollider.SoundMap (Instrument)  import qualified Sound.SC3.Server.NRT       as SCNRT@@ -16,12 +17,20 @@ -- import Sound.OpenSoundControl.Transport (Transport) -- import qualified Sound.OpenSoundControl.Transport.Monad as Trans +import Sound.OpenSoundControl.OSC (OSC(Bundle))+import qualified Sound.OpenSoundControl.Time as OSCTime+ import qualified Data.ByteString.Lazy as B  import qualified Haskore.Melody as Melody  import qualified Haskore.RealTime.Timer.Immediate as TimerImmediate+import qualified Haskore.RealTime.EventList.TimeBody as TimeList +import qualified Data.EventList.Absolute.TimeBody as AbsoluteEventList++import qualified Numeric.NonNegative.Wrapper as NonNeg+ import System.Cmd (rawSystem) import System.Exit (ExitCode) @@ -92,6 +101,25 @@  byteStringFromSchedule :: Schedule.T -> B.ByteString byteStringFromSchedule =-   SCNRT.encodeNRT .-   Schedule.toStream+   SCNRT.encodeNRT . scheduleToStream +scheduleToStream ::+   Schedule.T ->+   [OSC]+scheduleToStream sc =+   timeStamp 0 (Schedule.initial sc) :+   messagesToStream (Schedule.body sc)++messagesToStream ::+   TimeList.T Time OSC ->+   [OSC]+messagesToStream =+   map (uncurry timeStamp) .+   AbsoluteEventList.toPairList .+   {- first absolutize, then collectCoincident in order to catch+      coincidences caused by rounding -}+   AbsoluteEventList.collectCoincident .+   TimeList.toAbsoluteEventList 0++timeStamp :: Time -> [OSC] -> OSC+timeStamp = Bundle . OSCTime.NTPr . NonNeg.toNumber
src/Haskore/Interface/SuperCollider/Schedule.hs view
@@ -9,13 +9,9 @@     -- for Play module     installUGenMsg, installSoundMsg,     defaultChannel, atomPlayMsg,-    timeStamp, -    -- for Render module-    toStream,-     -- for suppression of "unused" warnings :-)-    fromMusicMsgs, messagesToStream, eventToMark,+    fromMusicMsgs, eventToMark,      -- testing     -- fromMelodyPerformance,@@ -28,9 +24,7 @@  import Sound.SC3.UGen.UGen (UGen) --- import qualified Sound.OpenSoundControl.Transport.UDP      as UDP--- import qualified Sound.OpenSoundControl.UDPMonad as UDP-import Sound.OpenSoundControl.OSC (OSC(Bundle))+import Sound.OpenSoundControl.OSC (OSC)  import qualified Haskore.Interface.SuperCollider.Note          as Note import qualified Haskore.Interface.SuperCollider.Performance   as SCPf@@ -46,17 +40,16 @@ import qualified Haskore.Music             as Music  import qualified Haskore.Performance.BackEnd      as PfBE-import qualified Haskore.RealTime.EventList.TimeBody    as TimeList+import qualified Haskore.RealTime.EventList.TimeBody as TimeList import qualified Haskore.RealTime.EventList.TimeTime as TimeListPad-import qualified Data.EventList.Absolute.TimeBody as AbsoluteEventList  import qualified Haskore.General.IdGenerator      as IdGen  import qualified Numeric.NonNegative.Wrapper as NonNeg -import Control.Monad (liftM2)+import Control.Monad (liftM2, ) -import Data.Maybe(fromMaybe,maybeToList)+import Data.Maybe(fromMaybe, maybeToList, )   {- * Schedule data structure -}@@ -235,32 +228,7 @@    TimeListPad.mapBody (uncurry eventToMsg)  -toStream ::-   T ->-   [OSC]-toStream sc =-   timeStamp 0 (initial sc) :-   messagesToStream (body sc) -messagesToStream ::-   TimeList.T Time OSC ->-   [OSC]-messagesToStream =-   map (uncurry timeStamp) .-   AbsoluteEventList.toPairList .-   {- first absolutize, then collectCoincident in order to catch-      coincidences caused by rounding -}-   AbsoluteEventList.collectCoincident .-   TimeList.toAbsoluteEventList 0--timeStamp :: Time -> [OSC] -> OSC-timeStamp = Bundle . NonNeg.toNumber------ {- * Construction of OpenSoundControl messages -}  stopMsg :: OSC@@ -289,7 +257,7 @@    UGen ->    OSC installUGenMsg name chan =-   SCPlay.d_recv' name .+   SCPlay.d_recv_synthdef name .    Channel.writeUGen chan  installSoundMsg ::
src/Haskore/Interface/SuperCollider/Schedule/Channel.hs view
@@ -42,9 +42,11 @@  import qualified Haskore.General.IdGenerator      as IdGen -import qualified Control.Monad.State as State-import Control.Monad.State  (StateT, runStateT, lift, liftM2, get, put)-import Control.Monad.Writer (Writer, tell, runWriter)+import qualified Control.Monad.Trans.State as State+import Control.Monad.Trans.State  (StateT, runStateT, get, put, )+import Control.Monad.Trans.Writer (Writer, tell, runWriter, )+import Control.Monad.Trans (lift, )+import Control.Monad (liftM2, )   
src/Haskore/Interface/SuperCollider/Schedule/Install.hs view
@@ -28,7 +28,7 @@ import           Haskore.Melody         as Melody  -import Control.Monad.Writer (MonadWriter, Writer, tell, runWriter)+import Control.Monad.Trans.Writer (Writer, tell, runWriter)   
src/Haskore/Interface/SuperCollider/SoundMap.hs view
@@ -13,8 +13,8 @@  import Sound.SC3.UGen.UGen (UGen) -import Haskore.General.Utility (toMaybe)-import Data.Maybe (mapMaybe)+import Data.Maybe.HT (toMaybe, )+import Data.Maybe (mapMaybe, )   {- * Generic definitions -}
+ src/Haskore/Interface/SuperCollider/Timer.hs view
@@ -0,0 +1,10 @@+module Haskore.Interface.SuperCollider.Timer where++import qualified Haskore.RealTime.Timer           as Timer+import qualified Haskore.RealTime.Timer.Thread as TimerThread++import Control.Monad.Trans (MonadIO, )+++timer :: MonadIO io => Timer.T io+timer = Timer.liftIO TimerThread.timer