module Haskore.Interface.SuperCollider.Play (
music, melody, performance,
schedule, scheduleWithPlayer, shutUp,
defaultLatency, timeStamp,
installSound, playAtom,
performanceTrans, messagesGrouped,
messagesGroupedManual, messagesSingly, messagesSimple,
) where
import qualified Haskore.Interface.SuperCollider.Schedule as Schedule
import Haskore.Interface.SuperCollider.Schedule (Time)
import qualified Haskore.Interface.SuperCollider.Performance as SCPf
import qualified Haskore.Interface.SuperCollider.SoundMap as SoundMap
import Haskore.Interface.SuperCollider.SoundMap (Instrument, Sound)
import qualified Sound.SC3.Server.PlayEasy as SCPlay
import qualified Sound.OpenSoundControl.Transport.Monad as Trans
import Sound.OpenSoundControl.OSC (OSC(Bundle))
import qualified Sound.OpenSoundControl.Time as OSCTime
import qualified Haskore.Melody as Melody
import qualified Haskore.Music as Music
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 Numeric.NonNegative.Wrapper as NonNeg
import Control.Monad.IO.Class (MonadIO, )
import Control.Monad (liftM, )
music :: Ord note =>
Time ->
Schedule.SoundHandler note ->
Music.T note ->
IO ()
music latency soundHandler =
schedule latency .
Schedule.fromMusic soundHandler
melody :: Time -> Instrument -> Melody.T () -> IO ()
melody latency sound =
schedule latency .
Schedule.fromMelody sound
performanceTrans :: (Trans.C m, MonadIO m) =>
Time ->
[OSC] ->
SCPf.T Time ->
m ()
performanceTrans latency installMsgs =
scheduleWithPlayer
(messagesGrouped SCTimer.timer latency) .
Schedule.fromPerformance installMsgs []
performance ::
Time ->
[OSC] ->
SCPf.T Time ->
IO ()
performance latency installMsgs =
schedule latency .
Schedule.fromPerformance installMsgs []
schedule ::
Time ->
Schedule.T ->
IO ()
schedule latency =
SCPlay.withSC3 .
scheduleWithPlayer
(messagesGrouped SCTimer.timer latency)
shutUp :: IO ()
shutUp =
do SCPlay.withSC3 SCPlay.stop
return ()
defaultLatency :: Time
defaultLatency = 0.1
timeStamp :: Time -> Time -> [OSC] -> OSC
timeStamp start t = Bundle $ OSCTime.UTCr $ NonNeg.toNumber (start+t)
installSound ::
(Trans.C m, SoundMap.SoundParameters params) =>
String ->
Sound params ->
m ()
installSound name instr =
SCPlay.simpleSync $ Schedule.installSoundMsg name Schedule.defaultChannel instr
playAtom :: Trans.C m =>
SCPlay.NodeId
-> String
-> [(String,Double)]
-> m ()
playAtom sid name params =
Trans.send (Schedule.atomPlayMsg sid name params)
scheduleWithPlayer :: Trans.C m =>
(TimeList.T Time OSC -> m ()) ->
Schedule.T ->
m ()
scheduleWithPlayer player sc =
do
let isc = Schedule.initial sc
mapM_ Trans.send isc
mapM_ (const (Trans.wait "/done" >> return ())) isc
player (Schedule.body sc)
return ()
messagesGrouped :: (Trans.C m) =>
Timer.T m ->
Time ->
TimeList.T Time OSC -> m ()
messagesGrouped timer latency =
liftM (const ()) .
TimeList.runTimeStampGrouped timer
(\time -> Trans.send . timeStamp latency time)
messagesGroupedManual :: (Trans.C m) =>
Timer.T m ->
Time ->
TimeList.T Time OSC -> m ()
messagesGroupedManual timer latency =
liftM (const ()) .
TimeList.runTimeStamp timer
(\time ->
(Trans.send . timeStamp latency time))
. TimeList.collectCoincident
messagesSingly :: (Trans.C m) =>
Timer.T m ->
Time ->
TimeList.T Time OSC -> m ()
messagesSingly timer latency =
liftM (const ()) .
TimeList.runTimeStamp timer
(\time ->
(Trans.send . timeStamp latency time . (:[])))
messagesSimple :: (Trans.C m) =>
Timer.T m ->
TimeList.T Time OSC ->
m ()
messagesSimple timer =
liftM (const ()) .
TimeList.run timer Trans.send