packages feed

zwirn-0.2.3.1: src/zwirn-doux/Zwirn/Doux/UI.hs

module Zwirn.Doux.UI where

import Control.Concurrent.MVar
import qualified Data.Map as Map
import qualified Data.Text as T
import Sound.Doux.Engine
import Sound.Tidal.Clock
import qualified Sound.Tidal.Clock as Clock
import Zwirn.Core.Lib.Modulate (shift)
import Zwirn.Doux.Process
import Zwirn.Doux.Types (Stream (..), StreamConfig (..))
import Zwirn.Language.Evaluate (Expression, Zwirn)
import Zwirn.Language.Play

startStream :: StreamConfig -> IO Stream
startStream config = do
  let conf = (streamConfigClock config) {clockFrameTimespan = 10 * realToFrac (streamConfigPrecision config)}
  d <- create (Config (streamConfigSamples config) (streamConfigInput config) (streamConfigOutput config) (streamConfigHost config) (streamConfigBufferSize config) (streamConfigChannels config) (streamConfigBlockSize config) (streamConfigMaxVoices config))

  zMV <- newMVar Map.empty
  stMV <- newMVar Map.empty
  busMapMV <- newMVar Map.empty
  actionMapMV <- newMVar Map.empty

  cref <- clocked conf (tickAction d zMV actionMapMV busMapMV stMV (streamConfigPrecision config))
  let str = Stream d zMV actionMapMV busMapMV stMV cref config
  streamSetBPM str (realToFrac streamDefaultBPM)
  return str

streamDefaultBPM :: Double
streamDefaultBPM = 138

streamSet :: Stream -> T.Text -> Expression -> IO ()
streamSet str x ex = modifyMVar_ (sState str) (return . Map.insert x ex)

streamSetCPS :: Stream -> Time -> IO ()
streamSetCPS str c = streamSetBPM str (c * toRational (clockBeatsPerCycle (streamConfigClock $ sConfig str) * 60))

-- | set the bpm in the clock
streamSetBPM :: Stream -> Time -> IO ()
streamSetBPM s = Clock.setBPM (sClockRef s)

streamGetBPM :: Stream -> IO Double
streamGetBPM str = realToFrac <$> Clock.getBPM (sClockRef str)

streamGetCPS :: Stream -> IO Double
streamGetCPS str = realToFrac <$> Clock.getCPS (streamConfigClock $ sConfig str) (sClockRef str)

streamResetCycles :: Stream -> IO ()
streamResetCycles s = streamSetCycle s 0

streamSetCycle :: Stream -> Time -> IO ()
streamSetCycle s = Clock.setClock (sClockRef s)

streamGetCycle :: Stream -> IO Int
streamGetCycle s = floor <$> streamGetNow s

streamEnableLink :: Stream -> IO ()
streamEnableLink s = Clock.enableLink (sClockRef s)

streamDisableLink :: Stream -> IO ()
streamDisableLink s = Clock.disableLink (sClockRef s)

streamGetNow :: Stream -> IO Time
streamGetNow s = Clock.getCycleTime (streamConfigClock $ sConfig s) (sClockRef s)

streamNudge :: Stream -> Double -> IO ()
streamNudge s = Clock.setNudge (sClockRef s)

streamFirst :: Stream -> Zwirn Expression -> IO ()
streamFirst str z = do
  dummy <- newMVar $ Map.singleton (TextID $ T.pack "_streamOnceDummy_") (Targeted [] (Normal, z, Nothing))
  Clock.clockOnce (tickActionOnce (sDoux str) dummy (sState str) (streamConfigPrecision $ sConfig str)) (streamConfigClock $ sConfig str) (sClockRef str)

streamNow :: Stream -> Zwirn Expression -> IO ()
streamNow str z = do
  now <- streamGetNow str
  dummy <- newMVar $ Map.singleton (TextID $ T.pack "_streamOnceDummy_") (Targeted [] (Normal, shift (realToFrac $ -now) z, Nothing))
  Clock.clockOnce (tickActionOnce (sDoux str) dummy (sState str) (streamConfigPrecision $ sConfig str)) (streamConfigClock $ sConfig str) (sClockRef str)