-- | The unit-generator graph structure implemented by the SuperCollider synthesis server.
module Sound.Sc3.Server.Synthdef where

import qualified Data.ByteString.Lazy as L {- bytestring -}

import qualified Sound.Sc3.Ugen.Graph as Graph {- hsc3 -}
import qualified Sound.Sc3.Ugen.Help.Graph as Help.Graph {- hsc3 -}
import qualified Sound.Sc3.Ugen.Ugen as Ugen {- hsc3 -}

import qualified Sound.Sc3.Server.Graphdef as Graphdef {- hsc3 -}
import qualified Sound.Sc3.Server.Graphdef.Binary as Graphdef.Binary {- hsc3 -}
import qualified Sound.Sc3.Server.Graphdef.Graph as Graphdef.Graph {- hsc3 -}
import qualified Sound.Sc3.Server.Param as Param {- hsc3 -}

-- | A named unit generator graph.
data Synthdef = Synthdef
  { Synthdef -> String
synthdefName :: String
  , Synthdef -> Ugen
synthdefUgen :: Ugen.Ugen
  }
  deriving (Synthdef -> Synthdef -> Bool
(Synthdef -> Synthdef -> Bool)
-> (Synthdef -> Synthdef -> Bool) -> Eq Synthdef
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Synthdef -> Synthdef -> Bool
== :: Synthdef -> Synthdef -> Bool
$c/= :: Synthdef -> Synthdef -> Bool
/= :: Synthdef -> Synthdef -> Bool
Eq, Int -> Synthdef -> ShowS
[Synthdef] -> ShowS
Synthdef -> String
(Int -> Synthdef -> ShowS)
-> (Synthdef -> String) -> ([Synthdef] -> ShowS) -> Show Synthdef
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Synthdef -> ShowS
showsPrec :: Int -> Synthdef -> ShowS
$cshow :: Synthdef -> String
show :: Synthdef -> String
$cshowList :: [Synthdef] -> ShowS
showList :: [Synthdef] -> ShowS
Show)

-- | Alias for 'Synthdef'.
synthdef :: String -> Ugen.Ugen -> Synthdef
synthdef :: String -> Ugen -> Synthdef
synthdef = String -> Ugen -> Synthdef
Synthdef

{- | The Sc3 /default/ instrument 'Synthdef', see 'default_ugen_graph'.

> import Sound.Osc {\- hosc -\}
> import Sound.Sc3 {\- hsc3 -\}
> withSc3 (sendMessage (d_recv defaultSynthdef))
> audition defaultSynthdef
-}
defaultSynthdef :: Synthdef
defaultSynthdef :: Synthdef
defaultSynthdef = String -> Ugen -> Synthdef
synthdef String
"default" Ugen
Help.Graph.default_ugen_graph

{- | The Sc3 /default/ sample (buffer) playback instrument 'Synthdef',
see 'default_sampler_ugen_graph'.

> withSc3 (sendMessage (d_recv (defaultSampler False)))
> audition (defaultSampler False)
-}
defaultSampler :: Bool -> Synthdef
defaultSampler :: Bool -> Synthdef
defaultSampler Bool
use_gate =
  let nm :: String
nm = String
"default-sampler-" String -> ShowS
forall a. [a] -> [a] -> [a]
++ if Bool
use_gate then String
"gate" else String
"fixed"
  in String -> Ugen -> Synthdef
synthdef String
nm (Bool -> Ugen
Help.Graph.default_sampler_ugen_graph Bool
use_gate)

-- | 'ugen_to_graph' of 'synthdefUgen'.
synthdefGraph :: Synthdef -> Graph.U_Graph
synthdefGraph :: Synthdef -> U_Graph
synthdefGraph = Ugen -> U_Graph
Graph.ugen_to_graph (Ugen -> U_Graph) -> (Synthdef -> Ugen) -> Synthdef -> U_Graph
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Synthdef -> Ugen
synthdefUgen

{- | Parameter names at 'Synthdef'.

>>> synthdefParam defaultSynthdef
[("amp",0.1),("pan",0.0),("gate",1.0),("freq",440.0),("out",0.0)]
-}
synthdefParam :: Synthdef -> Param.Param
synthdefParam :: Synthdef -> Param
synthdefParam =
  (U_Node -> Param1) -> [U_Node] -> Param
forall a b. (a -> b) -> [a] -> [b]
map (\U_Node
n -> (U_Node -> String
Graph.u_node_k_name U_Node
n, U_Node -> Sample
Graph.u_node_k_default U_Node
n))
    ([U_Node] -> Param) -> (Synthdef -> [U_Node]) -> Synthdef -> Param
forall b c a. (b -> c) -> (a -> b) -> a -> c
. U_Graph -> [U_Node]
Graph.ug_controls
    (U_Graph -> [U_Node])
-> (Synthdef -> U_Graph) -> Synthdef -> [U_Node]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Synthdef -> U_Graph
synthdefGraph

-- | 'graph_to_graphdef' at 'Synthdef'.
synthdef_to_graphdef :: Synthdef -> Graphdef.Graphdef
synthdef_to_graphdef :: Synthdef -> Graphdef
synthdef_to_graphdef (Synthdef String
nm Ugen
u) = String -> U_Graph -> Graphdef
Graphdef.Graph.graph_to_graphdef String
nm (Ugen -> U_Graph
Graph.ugen_to_graph Ugen
u)

-- | 'graph_to_graphdef' at 'Synthdef'.
ugen_to_graphdef :: Ugen.Ugen -> Graphdef.Graphdef
ugen_to_graphdef :: Ugen -> Graphdef
ugen_to_graphdef = Synthdef -> Graphdef
synthdef_to_graphdef (Synthdef -> Graphdef) -> (Ugen -> Synthdef) -> Ugen -> Graphdef
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Ugen -> Synthdef
Synthdef String
"anonymous"

-- | Encode 'Synthdef' as a binary data stream.
synthdefData :: Synthdef -> L.ByteString
synthdefData :: Synthdef -> ByteString
synthdefData = Graphdef -> ByteString
Graphdef.Binary.encode_graphdef (Graphdef -> ByteString)
-> (Synthdef -> Graphdef) -> Synthdef -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Synthdef -> Graphdef
synthdef_to_graphdef

-- | Write 'Synthdef' to indicated file.
synthdefWrite :: FilePath -> Synthdef -> IO ()
synthdefWrite :: String -> Synthdef -> IO ()
synthdefWrite String
fn = String -> Graphdef -> IO ()
Graphdef.Binary.graphdefWrite String
fn (Graphdef -> IO ()) -> (Synthdef -> Graphdef) -> Synthdef -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Synthdef -> Graphdef
synthdef_to_graphdef

{- | Write 'Synthdef' to indicated directory.  The filename is the
'synthdefName' with the appropriate extension (@scsyndef@).
-}
synthdefWrite_dir :: FilePath -> Synthdef -> IO ()
synthdefWrite_dir :: String -> Synthdef -> IO ()
synthdefWrite_dir String
dir = String -> Graphdef -> IO ()
Graphdef.Binary.graphdefWrite_dir String
dir (Graphdef -> IO ()) -> (Synthdef -> Graphdef) -> Synthdef -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Synthdef -> Graphdef
synthdef_to_graphdef

-- | 'graph_stat_ln' of 'synth'.
synthstat_ln :: Ugen.Ugen -> [String]
synthstat_ln :: Ugen -> [String]
synthstat_ln = U_Graph -> [String]
Graph.ug_stat_ln (U_Graph -> [String]) -> (Ugen -> U_Graph) -> Ugen -> [String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Ugen -> U_Graph
Graph.ugen_to_graph

-- | 'unlines' of 'synthstat_ln'.
synthstat :: Ugen.Ugen -> String
synthstat :: Ugen -> String
synthstat = [String] -> String
unlines ([String] -> String) -> (Ugen -> [String]) -> Ugen -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Ugen -> [String]
synthstat_ln

{- | 'putStrLn' of 'synthstat'.

> synthstat_wr Sound.Sc3.Ugen.Help.Graph.default_ugen_graph
-}
synthstat_wr :: Ugen.Ugen -> IO ()
synthstat_wr :: Ugen -> IO ()
synthstat_wr = String -> IO ()
putStrLn (String -> IO ()) -> (Ugen -> String) -> Ugen -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Ugen -> String
synthstat

{- | Variant without Ugen sequence.

> putStrLn $ synthstat_concise (default_sampler_ugen_graph True)
-}
synthstat_concise :: Ugen.Ugen -> String
synthstat_concise :: Ugen -> String
synthstat_concise = [String] -> String
unlines ([String] -> String) -> (Ugen -> [String]) -> Ugen -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [String] -> [String]
forall a. [a] -> [a]
reverse ([String] -> [String]) -> (Ugen -> [String]) -> Ugen -> [String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> [String] -> [String]
forall a. Int -> [a] -> [a]
drop Int
1 ([String] -> [String]) -> (Ugen -> [String]) -> Ugen -> [String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [String] -> [String]
forall a. [a] -> [a]
reverse ([String] -> [String]) -> (Ugen -> [String]) -> Ugen -> [String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Ugen -> [String]
synthstat_ln

-- | 'graphdef_dump_ugens' of 'ugen_to_graphdef'
ugen_dump_ugens :: Ugen.Ugen -> IO ()
ugen_dump_ugens :: Ugen -> IO ()
ugen_dump_ugens = Graphdef -> IO ()
Graphdef.graphdef_dump_ugens (Graphdef -> IO ()) -> (Ugen -> Graphdef) -> Ugen -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Ugen -> Graphdef
ugen_to_graphdef