{-
    Safe/Context.hs - wraps UI functions
    Copyright (C) 2021 Johannes Waldmann and contributors

    Forked from:
    https://github.com/jwaldmann/safe-tidal-cli/

    This library is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this library.  If not, see <http://www.gnu.org/licenses/>.
-}

{-# language GeneralizedNewtypeDeriving #-}
{-# language NoMonomorphismRestriction #-}

module Sound.Tidal.Safe.Context
  ( Op () -- do not export constructor,
    -- so the user has no way of putting arbitraty IO stuff
    -- in "Op", and below "run"
  , exec
  , streamReplace
  , streamHush
  , streamList
  , streamMute
  , streamUnmute
  , streamSolo
  , streamUnsolo
  , streamOnce
  , streamFirst
  , streamNudgeAll
  , streamAll
  , streamResetCycles
  , streamSetI
  , streamSetF
  , streamSetS
  , streamSetR
  , streamSetB
  , transition
  , module C
  , startTidal, superdirtTarget, Target(..)
  )
where

import Data.Ratio as C
import Sound.Tidal.Carabiner as C
import Sound.Tidal.Config as C
import Sound.Tidal.Control as C
import Sound.Tidal.Core as C
import Sound.Tidal.Params as C
import Sound.Tidal.ParseBP as C
import Sound.Tidal.Pattern as C
import Sound.Tidal.Scales as C
import Sound.Tidal.Simple as C
import Sound.Tidal.Stream
  (startTidal, superdirtTarget, Target(..))
-- import Sound.Tidal.Transition as C
import Sound.Tidal.UI as C
import Sound.Tidal.Version as C
import Sound.Tidal.EspGrid as C

import qualified Sound.Tidal.Context as C
import Sound.Tidal.Context
  (Stream, Pattern, ControlPattern, Time)
import Control.Monad.Reader
import Control.Monad.Catch

newtype Op r = Op ( ReaderT Stream IO r )
  deriving (a -> Op b -> Op a
(a -> b) -> Op a -> Op b
(forall a b. (a -> b) -> Op a -> Op b)
-> (forall a b. a -> Op b -> Op a) -> Functor Op
forall a b. a -> Op b -> Op a
forall a b. (a -> b) -> Op a -> Op b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: a -> Op b -> Op a
$c<$ :: forall a b. a -> Op b -> Op a
fmap :: (a -> b) -> Op a -> Op b
$cfmap :: forall a b. (a -> b) -> Op a -> Op b
Functor, Functor Op
a -> Op a
Functor Op
-> (forall a. a -> Op a)
-> (forall a b. Op (a -> b) -> Op a -> Op b)
-> (forall a b c. (a -> b -> c) -> Op a -> Op b -> Op c)
-> (forall a b. Op a -> Op b -> Op b)
-> (forall a b. Op a -> Op b -> Op a)
-> Applicative Op
Op a -> Op b -> Op b
Op a -> Op b -> Op a
Op (a -> b) -> Op a -> Op b
(a -> b -> c) -> Op a -> Op b -> Op c
forall a. a -> Op a
forall a b. Op a -> Op b -> Op a
forall a b. Op a -> Op b -> Op b
forall a b. Op (a -> b) -> Op a -> Op b
forall a b c. (a -> b -> c) -> Op a -> Op b -> Op c
forall (f :: * -> *).
Functor f
-> (forall a. a -> f a)
-> (forall a b. f (a -> b) -> f a -> f b)
-> (forall a b c. (a -> b -> c) -> f a -> f b -> f c)
-> (forall a b. f a -> f b -> f b)
-> (forall a b. f a -> f b -> f a)
-> Applicative f
<* :: Op a -> Op b -> Op a
$c<* :: forall a b. Op a -> Op b -> Op a
*> :: Op a -> Op b -> Op b
$c*> :: forall a b. Op a -> Op b -> Op b
liftA2 :: (a -> b -> c) -> Op a -> Op b -> Op c
$cliftA2 :: forall a b c. (a -> b -> c) -> Op a -> Op b -> Op c
<*> :: Op (a -> b) -> Op a -> Op b
$c<*> :: forall a b. Op (a -> b) -> Op a -> Op b
pure :: a -> Op a
$cpure :: forall a. a -> Op a
$cp1Applicative :: Functor Op
Applicative, Applicative Op
a -> Op a
Applicative Op
-> (forall a b. Op a -> (a -> Op b) -> Op b)
-> (forall a b. Op a -> Op b -> Op b)
-> (forall a. a -> Op a)
-> Monad Op
Op a -> (a -> Op b) -> Op b
Op a -> Op b -> Op b
forall a. a -> Op a
forall a b. Op a -> Op b -> Op b
forall a b. Op a -> (a -> Op b) -> Op b
forall (m :: * -> *).
Applicative m
-> (forall a b. m a -> (a -> m b) -> m b)
-> (forall a b. m a -> m b -> m b)
-> (forall a. a -> m a)
-> Monad m
return :: a -> Op a
$creturn :: forall a. a -> Op a
>> :: Op a -> Op b -> Op b
$c>> :: forall a b. Op a -> Op b -> Op b
>>= :: Op a -> (a -> Op b) -> Op b
$c>>= :: forall a b. Op a -> (a -> Op b) -> Op b
$cp1Monad :: Applicative Op
Monad, MonadThrow Op
MonadThrow Op
-> (forall e a. Exception e => Op a -> (e -> Op a) -> Op a)
-> MonadCatch Op
Op a -> (e -> Op a) -> Op a
forall e a. Exception e => Op a -> (e -> Op a) -> Op a
forall (m :: * -> *).
MonadThrow m
-> (forall e a. Exception e => m a -> (e -> m a) -> m a)
-> MonadCatch m
catch :: Op a -> (e -> Op a) -> Op a
$ccatch :: forall e a. Exception e => Op a -> (e -> Op a) -> Op a
$cp1MonadCatch :: MonadThrow Op
MonadCatch,Monad Op
e -> Op a
Monad Op -> (forall e a. Exception e => e -> Op a) -> MonadThrow Op
forall e a. Exception e => e -> Op a
forall (m :: * -> *).
Monad m -> (forall e a. Exception e => e -> m a) -> MonadThrow m
throwM :: e -> Op a
$cthrowM :: forall e a. Exception e => e -> Op a
$cp1MonadThrow :: Monad Op
MonadThrow)

exec :: Stream -> Op r -> IO r
exec :: Stream -> Op r -> IO r
exec Stream
s (Op ReaderT Stream IO r
m) = ReaderT Stream IO r -> Stream -> IO r
forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT ReaderT Stream IO r
m Stream
s

op1 :: (Stream -> IO r) -> Op r
op1 Stream -> IO r
f         = ReaderT Stream IO r -> Op r
forall r. ReaderT Stream IO r -> Op r
Op (ReaderT Stream IO r -> Op r) -> ReaderT Stream IO r -> Op r
forall a b. (a -> b) -> a -> b
$ do Stream
a <- ReaderT Stream IO Stream
forall r (m :: * -> *). MonadReader r m => m r
ask; IO r -> ReaderT Stream IO r
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (IO r -> ReaderT Stream IO r) -> IO r -> ReaderT Stream IO r
forall a b. (a -> b) -> a -> b
$ Stream -> IO r
f Stream
a
op2 :: (Stream -> t -> IO r) -> t -> Op r
op2 Stream -> t -> IO r
f t
b       = ReaderT Stream IO r -> Op r
forall r. ReaderT Stream IO r -> Op r
Op (ReaderT Stream IO r -> Op r) -> ReaderT Stream IO r -> Op r
forall a b. (a -> b) -> a -> b
$ do Stream
a <- ReaderT Stream IO Stream
forall r (m :: * -> *). MonadReader r m => m r
ask; IO r -> ReaderT Stream IO r
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (IO r -> ReaderT Stream IO r) -> IO r -> ReaderT Stream IO r
forall a b. (a -> b) -> a -> b
$ Stream -> t -> IO r
f Stream
a t
b 
op3 :: (Stream -> t -> t -> IO r) -> t -> t -> Op r
op3 Stream -> t -> t -> IO r
f t
b t
c     = ReaderT Stream IO r -> Op r
forall r. ReaderT Stream IO r -> Op r
Op (ReaderT Stream IO r -> Op r) -> ReaderT Stream IO r -> Op r
forall a b. (a -> b) -> a -> b
$ do Stream
a <- ReaderT Stream IO Stream
forall r (m :: * -> *). MonadReader r m => m r
ask; IO r -> ReaderT Stream IO r
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (IO r -> ReaderT Stream IO r) -> IO r -> ReaderT Stream IO r
forall a b. (a -> b) -> a -> b
$ Stream -> t -> t -> IO r
f Stream
a t
b t
c
op4 :: (Stream -> t -> t -> t -> IO r) -> t -> t -> t -> Op r
op4 Stream -> t -> t -> t -> IO r
f t
b t
c t
d   = ReaderT Stream IO r -> Op r
forall r. ReaderT Stream IO r -> Op r
Op (ReaderT Stream IO r -> Op r) -> ReaderT Stream IO r -> Op r
forall a b. (a -> b) -> a -> b
$ do Stream
a <- ReaderT Stream IO Stream
forall r (m :: * -> *). MonadReader r m => m r
ask; IO r -> ReaderT Stream IO r
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (IO r -> ReaderT Stream IO r) -> IO r -> ReaderT Stream IO r
forall a b. (a -> b) -> a -> b
$ Stream -> t -> t -> t -> IO r
f Stream
a t
b t
c t
d
op5 :: (Stream -> t -> t -> t -> t -> IO r) -> t -> t -> t -> t -> Op r
op5 Stream -> t -> t -> t -> t -> IO r
f t
b t
c t
d t
e = ReaderT Stream IO r -> Op r
forall r. ReaderT Stream IO r -> Op r
Op (ReaderT Stream IO r -> Op r) -> ReaderT Stream IO r -> Op r
forall a b. (a -> b) -> a -> b
$ do Stream
a <- ReaderT Stream IO Stream
forall r (m :: * -> *). MonadReader r m => m r
ask; IO r -> ReaderT Stream IO r
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (IO r -> ReaderT Stream IO r) -> IO r -> ReaderT Stream IO r
forall a b. (a -> b) -> a -> b
$ Stream -> t -> t -> t -> t -> IO r
f Stream
a t
b t
c t
d t
e

streamReplace :: ID -> ControlPattern -> Op ()
streamReplace = (Stream -> ID -> ControlPattern -> IO ())
-> ID -> ControlPattern -> Op ()
forall t t r. (Stream -> t -> t -> IO r) -> t -> t -> Op r
op3 Stream -> ID -> ControlPattern -> IO ()
C.streamReplace
streamHush :: Op ()
streamHush = (Stream -> IO ()) -> Op ()
forall r. (Stream -> IO r) -> Op r
op1 Stream -> IO ()
C.streamHush
streamList :: Op ()
streamList = (Stream -> IO ()) -> Op ()
forall r. (Stream -> IO r) -> Op r
op1 Stream -> IO ()
C.streamList
streamMute :: ID -> Op ()
streamMute = (Stream -> ID -> IO ()) -> ID -> Op ()
forall t r. (Stream -> t -> IO r) -> t -> Op r
op2 Stream -> ID -> IO ()
C.streamMute
streamUnmute :: ID -> Op ()
streamUnmute = (Stream -> ID -> IO ()) -> ID -> Op ()
forall t r. (Stream -> t -> IO r) -> t -> Op r
op2 Stream -> ID -> IO ()
C.streamUnmute
streamSolo :: ID -> Op ()
streamSolo = (Stream -> ID -> IO ()) -> ID -> Op ()
forall t r. (Stream -> t -> IO r) -> t -> Op r
op2 Stream -> ID -> IO ()
C.streamSolo
streamUnsolo :: ID -> Op ()
streamUnsolo = (Stream -> ID -> IO ()) -> ID -> Op ()
forall t r. (Stream -> t -> IO r) -> t -> Op r
op2 Stream -> ID -> IO ()
C.streamUnsolo
streamOnce :: ControlPattern -> Op ()
streamOnce = (Stream -> ControlPattern -> IO ()) -> ControlPattern -> Op ()
forall t r. (Stream -> t -> IO r) -> t -> Op r
op2 Stream -> ControlPattern -> IO ()
C.streamOnce
streamFirst :: ControlPattern -> Op ()
streamFirst = (Stream -> ControlPattern -> IO ()) -> ControlPattern -> Op ()
forall t r. (Stream -> t -> IO r) -> t -> Op r
op2 Stream -> ControlPattern -> IO ()
C.streamFirst
streamNudgeAll :: Double -> Op ()
streamNudgeAll = (Stream -> Double -> IO ()) -> Double -> Op ()
forall t r. (Stream -> t -> IO r) -> t -> Op r
op2 Stream -> Double -> IO ()
C.streamNudgeAll
streamAll :: (ControlPattern -> ControlPattern) -> Op ()
streamAll = (Stream -> (ControlPattern -> ControlPattern) -> IO ())
-> (ControlPattern -> ControlPattern) -> Op ()
forall t r. (Stream -> t -> IO r) -> t -> Op r
op2 Stream -> (ControlPattern -> ControlPattern) -> IO ()
C.streamAll
streamResetCycles :: Op ()
streamResetCycles = (Stream -> IO ()) -> Op ()
forall r. (Stream -> IO r) -> Op r
op1 Stream -> IO ()
C.streamResetCycles
transition :: Bool
-> (Time -> [ControlPattern] -> ControlPattern)
-> ID
-> ControlPattern
-> Op ()
transition = (Stream
 -> Bool
 -> (Time -> [ControlPattern] -> ControlPattern)
 -> ID
 -> ControlPattern
 -> IO ())
-> Bool
-> (Time -> [ControlPattern] -> ControlPattern)
-> ID
-> ControlPattern
-> Op ()
forall t t t t r.
(Stream -> t -> t -> t -> t -> IO r) -> t -> t -> t -> t -> Op r
op5 Stream
-> Bool
-> (Time -> [ControlPattern] -> ControlPattern)
-> ID
-> ControlPattern
-> IO ()
C.transition
streamSetI :: String -> Pattern Int -> Op ()
streamSetI = (Stream -> String -> Pattern Int -> IO ())
-> String -> Pattern Int -> Op ()
forall t t r. (Stream -> t -> t -> IO r) -> t -> t -> Op r
op3 Stream -> String -> Pattern Int -> IO ()
C.streamSetI
streamSetF :: String -> Pattern Double -> Op ()
streamSetF = (Stream -> String -> Pattern Double -> IO ())
-> String -> Pattern Double -> Op ()
forall t t r. (Stream -> t -> t -> IO r) -> t -> t -> Op r
op3 Stream -> String -> Pattern Double -> IO ()
C.streamSetF
streamSetS :: String -> Pattern String -> Op ()
streamSetS = (Stream -> String -> Pattern String -> IO ())
-> String -> Pattern String -> Op ()
forall t t r. (Stream -> t -> t -> IO r) -> t -> t -> Op r
op3 Stream -> String -> Pattern String -> IO ()
C.streamSetS
streamSetR :: String -> Pattern Time -> Op ()
streamSetR = (Stream -> String -> Pattern Time -> IO ())
-> String -> Pattern Time -> Op ()
forall t t r. (Stream -> t -> t -> IO r) -> t -> t -> Op r
op3 Stream -> String -> Pattern Time -> IO ()
C.streamSetR
streamSetB :: String -> Pattern Bool -> Op ()
streamSetB = (Stream -> String -> Pattern Bool -> IO ())
-> String -> Pattern Bool -> Op ()
forall t t r. (Stream -> t -> t -> IO r) -> t -> t -> Op r
op3 Stream -> String -> Pattern Bool -> IO ()
C.streamSetB