{- | Binary 'Graph Definition' as understood by @scsynth@.
     There are both binary and text encoders and decoders.
-}
module Sound.Sc3.Server.Graphdef where

import Control.Monad {- base -}
import Data.List {- base -}
import Data.Maybe {- base -}
import Text.Printf {- base -}

import qualified Safe {- safe -}

import qualified Sound.Osc.Datum as Datum {- hosc -}

import qualified Sound.Sc3.Common.Math.Operator as Operator {- hsc3 -}
import qualified Sound.Sc3.Common.Rate as Rate {- hsc3 -}

-- * Type

-- | Names are Ascii strings (ie. ByteString.Char8)
type Name = Datum.Ascii

-- | Controls are a name and a ugen-index.
type Control = (Name, Int)

-- | Constants are floating point.
type Sample = Double

-- | Ugen indices are Int.
type Ugen_Index = Int

-- | Port indices are Int.
type Port_Index = Int

{- | Index used to indicate constants at Ugen inputs.
  Ie. if the ugen-index is this value (-1) it indicates a constant.
-}
constant_index :: Ugen_Index
constant_index :: Int
constant_index = -Int
1

-- | Inputs are a ugen-index and a port-index.
data Input = Input Ugen_Index Port_Index deriving (Input -> Input -> Bool
(Input -> Input -> Bool) -> (Input -> Input -> Bool) -> Eq Input
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Input -> Input -> Bool
== :: Input -> Input -> Bool
$c/= :: Input -> Input -> Bool
/= :: Input -> Input -> Bool
Eq, Int -> Input -> [Char] -> [Char]
[Input] -> [Char] -> [Char]
Input -> [Char]
(Int -> Input -> [Char] -> [Char])
-> (Input -> [Char]) -> ([Input] -> [Char] -> [Char]) -> Show Input
forall a.
(Int -> a -> [Char] -> [Char])
-> (a -> [Char]) -> ([a] -> [Char] -> [Char]) -> Show a
$cshowsPrec :: Int -> Input -> [Char] -> [Char]
showsPrec :: Int -> Input -> [Char] -> [Char]
$cshow :: Input -> [Char]
show :: Input -> [Char]
$cshowList :: [Input] -> [Char] -> [Char]
showList :: [Input] -> [Char] -> [Char]
Show)

-- | Rates are encoded as integers (IR = 0, KR = 1, AR = 2, DR = 3).
type Rate = Int

-- | Outputs each indicate a Rate.
type Output = Rate

-- | Secondary (special) index, used by operator Ugens to select operation.
type Special = Int

-- | Unit generator type.
type Ugen = (Name, Rate, [Input], [Output], Special)

-- | 'Ugen' name.
ugen_name_str :: Ugen -> String
ugen_name_str :: Ugen -> [Char]
ugen_name_str (Name
nm, Int
_, [Input]
_, [Int]
_, Int
_) = Name -> [Char]
Datum.ascii_to_string Name
nm

-- | 'Ugen' name, using operator name if appropriate.
ugen_name_op :: Ugen -> String
ugen_name_op :: Ugen -> [Char]
ugen_name_op (Name
nm, Int
_, [Input]
_, [Int]
_, Int
k) =
  let s :: [Char]
s = Name -> [Char]
Datum.ascii_to_string Name
nm
  in [Char] -> Maybe [Char] -> [Char]
forall a. a -> Maybe a -> a
fromMaybe [Char]
s ([Char] -> Int -> Maybe [Char]
Operator.ugen_operator_name [Char]
s Int
k)

-- | 'Ugen' 'Rate'.
ugen_rate :: Ugen -> Rate
ugen_rate :: Ugen -> Int
ugen_rate (Name
_, Int
r, [Input]
_, [Int]
_, Int
_) = Int
r

ugen_rate_enum :: Ugen -> Rate.Rate
ugen_rate_enum :: Ugen -> Rate
ugen_rate_enum = Int -> Rate
forall a. Enum a => Int -> a
toEnum (Int -> Rate) -> (Ugen -> Int) -> Ugen -> Rate
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Ugen -> Int
ugen_rate

-- | 'Ugen' 'Input's.
ugen_inputs :: Ugen -> [Input]
ugen_inputs :: Ugen -> [Input]
ugen_inputs (Name
_, Int
_, [Input]
i, [Int]
_, Int
_) = [Input]
i

-- | 'Ugen' 'Output's.
ugen_outputs :: Ugen -> [Output]
ugen_outputs :: Ugen -> [Int]
ugen_outputs (Name
_, Int
_, [Input]
_, [Int]
o, Int
_) = [Int]
o

-- | Predicate to examine Ugen name and decide if it is a control.
ugen_is_control :: Ugen -> Bool
ugen_is_control :: Ugen -> Bool
ugen_is_control =
  ([Char] -> [[Char]] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [[Char]
"Control", [Char]
"LagControl", [Char]
"TrigControl"])
    ([Char] -> Bool) -> (Ugen -> [Char]) -> Ugen -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Ugen -> [Char]
ugen_name_str

-- | Input is a Ugen (ie. not a constant, indicated by a ugen-index of -1) and the Ugen is a control.
input_is_control :: Graphdef -> Input -> Bool
input_is_control :: Graphdef -> Input -> Bool
input_is_control Graphdef
g (Input Int
u Int
_) = (Int
u Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
constant_index) Bool -> Bool -> Bool
&& Ugen -> Bool
ugen_is_control (Graphdef -> Int -> Ugen
graphdef_ugen Graphdef
g Int
u)

-- | Graph definition type.
data Graphdef = Graphdef
  { Graphdef -> Name
graphdef_name :: Name
  , Graphdef -> [Sample]
graphdef_constants :: [Sample]
  , Graphdef -> [(Control, Sample)]
graphdef_controls :: [(Control, Sample)]
  , Graphdef -> [Ugen]
graphdef_ugens :: [Ugen]
  }
  deriving (Graphdef -> Graphdef -> Bool
(Graphdef -> Graphdef -> Bool)
-> (Graphdef -> Graphdef -> Bool) -> Eq Graphdef
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Graphdef -> Graphdef -> Bool
== :: Graphdef -> Graphdef -> Bool
$c/= :: Graphdef -> Graphdef -> Bool
/= :: Graphdef -> Graphdef -> Bool
Eq, Int -> Graphdef -> [Char] -> [Char]
[Graphdef] -> [Char] -> [Char]
Graphdef -> [Char]
(Int -> Graphdef -> [Char] -> [Char])
-> (Graphdef -> [Char])
-> ([Graphdef] -> [Char] -> [Char])
-> Show Graphdef
forall a.
(Int -> a -> [Char] -> [Char])
-> (a -> [Char]) -> ([a] -> [Char] -> [Char]) -> Show a
$cshowsPrec :: Int -> Graphdef -> [Char] -> [Char]
showsPrec :: Int -> Graphdef -> [Char] -> [Char]
$cshow :: Graphdef -> [Char]
show :: Graphdef -> [Char]
$cshowList :: [Graphdef] -> [Char] -> [Char]
showList :: [Graphdef] -> [Char] -> [Char]
Show)

-- | Lookup Ugen by index.
graphdef_ugen :: Graphdef -> Ugen_Index -> Ugen
graphdef_ugen :: Graphdef -> Int -> Ugen
graphdef_ugen Graphdef
g = [Char] -> [Ugen] -> Int -> Ugen
forall a. Partial => [Char] -> [a] -> Int -> a
Safe.atNote [Char]
"graphdef_ugen" (Graphdef -> [Ugen]
graphdef_ugens Graphdef
g)

-- | Lookup Control and default value by index.
graphdef_control :: Graphdef -> Int -> (Control, Sample)
graphdef_control :: Graphdef -> Int -> (Control, Sample)
graphdef_control Graphdef
g = [Char] -> [(Control, Sample)] -> Int -> (Control, Sample)
forall a. Partial => [Char] -> [a] -> Int -> a
Safe.atNote [Char]
"graphdef_controls" (Graphdef -> [(Control, Sample)]
graphdef_controls Graphdef
g)

-- | nid of constant.
graphdef_constant_nid :: Graphdef -> Int -> Int
graphdef_constant_nid :: Graphdef -> Int -> Int
graphdef_constant_nid Graphdef
_ = Int -> Int
forall a. a -> a
id

-- | nid of control.
graphdef_control_nid :: Graphdef -> Int -> Int
graphdef_control_nid :: Graphdef -> Int -> Int
graphdef_control_nid Graphdef
g = Int -> Int -> Int
forall a. Num a => a -> a -> a
(+) ([Sample] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length (Graphdef -> [Sample]
graphdef_constants Graphdef
g))

-- | nid of Ugen.
graphdef_ugen_nid :: Graphdef -> Int -> Int
graphdef_ugen_nid :: Graphdef -> Int -> Int
graphdef_ugen_nid Graphdef
g Int
n = Graphdef -> Int -> Int
graphdef_control_nid Graphdef
g Int
0 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ [(Control, Sample)] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length (Graphdef -> [(Control, Sample)]
graphdef_controls Graphdef
g) Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
n

{- | "SCgf" encoded as 32-bit unsigned integer.

>> map fromEnum "SCgf"
[83, 67, 103, 102]

>>> import Sound.Osc.Coding.Byte
>>> decode_i32 (encode_ascii (Datum.ascii "SCgf")) == scgf_i32
True
-}
scgf_i32 :: Num n => n
scgf_i32 :: forall n. Num n => n
scgf_i32 = n
1396926310

-- * Get

-- | Get functions for Graphdef types, (str_f,i8_f,i16_f,i32_f,f32_f)
type Get_Functions m = (m Name, m Int, m Int, m Int, m Double)

-- | Get a 'Control'.
get_control :: Monad m => (Get_Functions m, m Int) -> m Control
get_control :: forall (m :: * -> *).
Monad m =>
(Get_Functions m, m Int) -> m Control
get_control ((m Name
get_str, m Int
_, m Int
_, m Int
_, m Sample
_), m Int
get_i) = do
  Name
nm <- m Name
get_str
  Int
ix <- m Int
get_i
  Control -> m Control
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Name
nm, Int
ix)

-- | Get an 'Input'.
get_input :: Monad m => m Int -> m Input
get_input :: forall (m :: * -> *). Monad m => m Int -> m Input
get_input m Int
get_i = (Int -> Int -> Input) -> m Int -> m Int -> m Input
forall (m :: * -> *) a1 a2 r.
Monad m =>
(a1 -> a2 -> r) -> m a1 -> m a2 -> m r
liftM2 Int -> Int -> Input
Input m Int
get_i m Int
get_i

-- | Get a 'Ugen'
get_ugen :: Monad m => (Get_Functions m, m Int) -> m Ugen
get_ugen :: forall (m :: * -> *). Monad m => (Get_Functions m, m Int) -> m Ugen
get_ugen ((m Name
get_str, m Int
get_i8, m Int
get_i16, m Int
_, m Sample
_), m Int
get_i) = do
  Name
name <- m Name
get_str
  Int
rate <- m Int
get_i8
  Int
number_of_inputs <- m Int
get_i
  Int
number_of_outputs <- m Int
get_i
  Int
special <- m Int
get_i16
  [Input]
inputs <- Int -> m Input -> m [Input]
forall (m :: * -> *) a. Applicative m => Int -> m a -> m [a]
replicateM Int
number_of_inputs (m Int -> m Input
forall (m :: * -> *). Monad m => m Int -> m Input
get_input m Int
get_i)
  [Int]
outputs <- Int -> m Int -> m [Int]
forall (m :: * -> *) a. Applicative m => Int -> m a -> m [a]
replicateM Int
number_of_outputs m Int
get_i8
  Ugen -> m Ugen
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return
    ( Name
name
    , Int
rate
    , [Input]
inputs
    , [Int]
outputs
    , Int
special
    )

-- | Get a 'Graphdef'. Supports version 0|1 and version 2 files.  Ignores variants.
get_graphdef :: Monad m => Get_Functions m -> m Graphdef
get_graphdef :: forall (m :: * -> *). Monad m => Get_Functions m -> m Graphdef
get_graphdef c :: Get_Functions m
c@(m Name
get_str, m Int
_, m Int
get_i16, m Int
get_i32, m Sample
get_f32) = do
  Int
magic <- m Int
get_i32
  Int
version <- m Int
get_i32
  let get_i :: m Int
get_i =
        case Int
version of
          Int
0 -> m Int
get_i16
          Int
1 -> m Int
get_i16 -- version one allows variants, which are not allowed by hsc3
          Int
2 -> m Int
get_i32
          Int
_ -> [Char] -> m Int
forall a. Partial => [Char] -> a
error ([Char]
"get_graphdef: version not at {zero | one | two}: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Int -> [Char]
forall a. Show a => a -> [Char]
show Int
version)
  Int
number_of_definitions <- m Int
get_i16
  Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when
    (Int
magic Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
forall n. Num n => n
scgf_i32)
    ([Char] -> m ()
forall a. Partial => [Char] -> a
error [Char]
"get_graphdef: illegal magic string")
  Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when
    (Int
number_of_definitions Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
1)
    ([Char] -> m ()
forall a. Partial => [Char] -> a
error [Char]
"get_graphdef: non unary graphdef file")
  Name
name <- m Name
get_str
  Int
number_of_constants <- m Int
get_i
  [Sample]
constants <- Int -> m Sample -> m [Sample]
forall (m :: * -> *) a. Applicative m => Int -> m a -> m [a]
replicateM Int
number_of_constants m Sample
get_f32
  Int
number_of_control_defaults <- m Int
get_i
  [Sample]
control_defaults <- Int -> m Sample -> m [Sample]
forall (m :: * -> *) a. Applicative m => Int -> m a -> m [a]
replicateM Int
number_of_control_defaults m Sample
get_f32
  Int
number_of_controls <- m Int
get_i
  [Control]
controls <- Int -> m Control -> m [Control]
forall (m :: * -> *) a. Applicative m => Int -> m a -> m [a]
replicateM Int
number_of_controls ((Get_Functions m, m Int) -> m Control
forall (m :: * -> *).
Monad m =>
(Get_Functions m, m Int) -> m Control
get_control (Get_Functions m
c, m Int
get_i))
  Int
number_of_ugens <- m Int
get_i
  [Ugen]
ugens <- Int -> m Ugen -> m [Ugen]
forall (m :: * -> *) a. Applicative m => Int -> m a -> m [a]
replicateM Int
number_of_ugens ((Get_Functions m, m Int) -> m Ugen
forall (m :: * -> *). Monad m => (Get_Functions m, m Int) -> m Ugen
get_ugen (Get_Functions m
c, m Int
get_i))
  Graphdef -> m Graphdef
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return
    ( Name -> [Sample] -> [(Control, Sample)] -> [Ugen] -> Graphdef
Graphdef
        Name
name
        [Sample]
constants
        ([Control] -> [Sample] -> [(Control, Sample)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Control]
controls [Sample]
control_defaults)
        [Ugen]
ugens
    )

-- * Encode (version zero)

-- | Encode functions for Graphdef types (join_f,str_f,i8_f,i16_f,i32_f,f32_f,com_f)
type Encode_Functions t = ([t] -> t, Name -> t, Int -> t, Int -> t, Int -> t, Double -> t, String -> t)

encode_input_f :: Encode_Functions t -> Input -> t
encode_input_f :: forall t. Encode_Functions t -> Input -> t
encode_input_f ([t] -> t
join_f, Name -> t
_, Int -> t
_, Int -> t
i16_f, Int -> t
_, Sample -> t
_, [Char] -> t
_) (Input Int
u Int
p) = [t] -> t
join_f ((Int -> t) -> [Int] -> [t]
forall a b. (a -> b) -> [a] -> [b]
map Int -> t
i16_f [Int
u, Int
p])

encode_control_f :: Encode_Functions t -> Control -> t
encode_control_f :: forall t. Encode_Functions t -> Control -> t
encode_control_f ([t] -> t
join_f, Name -> t
str_f, Int -> t
_, Int -> t
i16_f, Int -> t
_, Sample -> t
_, [Char] -> t
_) (Name
nm, Int
k) = [t] -> t
join_f [Name -> t
str_f Name
nm, Int -> t
i16_f Int
k]

encode_ugen_f :: Encode_Functions t -> Ugen -> t
encode_ugen_f :: forall t. Encode_Functions t -> Ugen -> t
encode_ugen_f Encode_Functions t
enc (Name
nm, Int
r, [Input]
i, [Int]
o, Int
s) =
  let ([t] -> t
join_f, Name -> t
str_f, Int -> t
i8_f, Int -> t
i16_f, Int -> t
_, Sample -> t
_, [Char] -> t
com_f) = Encode_Functions t
enc
  in [t] -> t
join_f
      [ [Char] -> t
com_f [Char]
"ugen-name"
      , Name -> t
str_f Name
nm
      , [Char] -> t
com_f [Char]
"ugen-rate"
      , Int -> t
i8_f Int
r
      , [Char] -> t
com_f [Char]
"ugen-number-of-inputs"
      , Int -> t
i16_f ([Input] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Input]
i)
      , [Char] -> t
com_f [Char]
"ugen-number-of-outputs"
      , Int -> t
i16_f ([Int] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Int]
o)
      , [Char] -> t
com_f [Char]
"ugen-special"
      , Int -> t
i16_f Int
s
      , [Char] -> t
com_f [Char]
"ugen-inputs (ugen-index,port-index)"
      , [t] -> t
join_f ((Input -> t) -> [Input] -> [t]
forall a b. (a -> b) -> [a] -> [b]
map (Encode_Functions t -> Input -> t
forall t. Encode_Functions t -> Input -> t
encode_input_f Encode_Functions t
enc) [Input]
i)
      , [Char] -> t
com_f [Char]
"ugen-output-rates"
      , [t] -> t
join_f ((Int -> t) -> [Int] -> [t]
forall a b. (a -> b) -> [a] -> [b]
map Int -> t
i8_f [Int]
o)
      ]

encode_graphdef_f :: Encode_Functions t -> Graphdef -> t
encode_graphdef_f :: forall t. Encode_Functions t -> Graphdef -> t
encode_graphdef_f Encode_Functions t
enc (Graphdef Name
nm [Sample]
cs [(Control, Sample)]
ks [Ugen]
us) =
  let ([t] -> t
join_f, Name -> t
str_f, Int -> t
_, Int -> t
i16_f, Int -> t
i32_f, Sample -> t
f32_f, [Char] -> t
com_f) = Encode_Functions t
enc
      ([Control]
ks_ctl, [Sample]
ks_def) = [(Control, Sample)] -> ([Control], [Sample])
forall a b. [(a, b)] -> ([a], [b])
unzip [(Control, Sample)]
ks
  in [t] -> t
join_f
      [ [Char] -> t
com_f [Char]
"SCgf"
      , Int -> t
i32_f Int
forall n. Num n => n
scgf_i32
      , [Char] -> t
com_f [Char]
"version"
      , Int -> t
i32_f Int
0
      , [Char] -> t
com_f [Char]
"number of graphs"
      , Int -> t
i16_f Int
1
      , [Char] -> t
com_f [Char]
"name"
      , Name -> t
str_f Name
nm
      , [Char] -> t
com_f [Char]
"number-of-constants"
      , Int -> t
i16_f ([Sample] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Sample]
cs)
      , [Char] -> t
com_f [Char]
"constant-values"
      , [t] -> t
join_f ((Sample -> t) -> [Sample] -> [t]
forall a b. (a -> b) -> [a] -> [b]
map Sample -> t
f32_f [Sample]
cs)
      , [Char] -> t
com_f [Char]
"number-of-controls"
      , Int -> t
i16_f ([Sample] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Sample]
ks_def)
      , [Char] -> t
com_f [Char]
"control-default-values"
      , [t] -> t
join_f ((Sample -> t) -> [Sample] -> [t]
forall a b. (a -> b) -> [a] -> [b]
map Sample -> t
f32_f [Sample]
ks_def)
      , [Char] -> t
com_f [Char]
"number-of-controls"
      , Int -> t
i16_f ([Control] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Control]
ks_ctl)
      , [Char] -> t
com_f [Char]
"controls"
      , [t] -> t
join_f ((Control -> t) -> [Control] -> [t]
forall a b. (a -> b) -> [a] -> [b]
map (Encode_Functions t -> Control -> t
forall t. Encode_Functions t -> Control -> t
encode_control_f Encode_Functions t
enc) [Control]
ks_ctl)
      , [Char] -> t
com_f [Char]
"number-of-ugens"
      , Int -> t
i16_f ([Ugen] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Ugen]
us)
      , [t] -> t
join_f ((Ugen -> t) -> [Ugen] -> [t]
forall a b. (a -> b) -> [a] -> [b]
map (Encode_Functions t -> Ugen -> t
forall t. Encode_Functions t -> Ugen -> t
encode_ugen_f Encode_Functions t
enc) [Ugen]
us)
      ]

-- * Stat

-- | Simple statistics printer for 'Graphdef'.
graphdef_stat :: Graphdef -> String
graphdef_stat :: Graphdef -> [Char]
graphdef_stat (Graphdef Name
nm [Sample]
cs [(Control, Sample)]
ks [Ugen]
us) =
  let f :: (a -> a) -> [a] -> [Char]
f a -> a
g =
        let h :: [a] -> (a, Int)
h (a
x : [a]
xs) = (a
x, [a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length (a
x a -> [a] -> [a]
forall a. a -> [a] -> [a]
: [a]
xs))
            h [] = [Char] -> (a, Int)
forall a. Partial => [Char] -> a
error [Char]
"graphdef_stat"
        in [(a, Int)] -> [Char]
forall a. Show a => a -> [Char]
show ([(a, Int)] -> [Char]) -> ([a] -> [(a, Int)]) -> [a] -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([a] -> (a, Int)) -> [[a]] -> [(a, Int)]
forall a b. (a -> b) -> [a] -> [b]
map [a] -> (a, Int)
forall {a}. [a] -> (a, Int)
h ([[a]] -> [(a, Int)]) -> ([a] -> [[a]]) -> [a] -> [(a, Int)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [a] -> [[a]]
forall a. Eq a => [a] -> [[a]]
group ([a] -> [[a]]) -> ([a] -> [a]) -> [a] -> [[a]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [a] -> [a]
forall a. Ord a => [a] -> [a]
sort ([a] -> [a]) -> ([a] -> [a]) -> [a] -> [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> a) -> [a] -> [a]
forall a b. (a -> b) -> [a] -> [b]
map a -> a
g
      sq :: ([[Char]] -> [[Char]]) -> [Char]
sq [[Char]] -> [[Char]]
pp_f = [Char] -> [[Char]] -> [Char]
forall a. [a] -> [[a]] -> [a]
intercalate [Char]
"," ([[Char]] -> [[Char]]
pp_f ((Ugen -> [Char]) -> [Ugen] -> [[Char]]
forall a b. (a -> b) -> [a] -> [b]
map Ugen -> [Char]
ugen_name_op [Ugen]
us))
  in [[Char]] -> [Char]
unlines
      [ [Char]
"name                      : " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Name -> [Char]
forall a. Show a => a -> [Char]
show Name
nm
      , [Char]
"number of constants       : " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Int -> [Char]
forall a. Show a => a -> [Char]
show ([Sample] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Sample]
cs)
      , [Char]
"number of controls        : " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Int -> [Char]
forall a. Show a => a -> [Char]
show ([(Control, Sample)] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [(Control, Sample)]
ks)
      , [Char]
"number of unit generators : " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Int -> [Char]
forall a. Show a => a -> [Char]
show ([Ugen] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Ugen]
us)
      , [Char]
"unit generator rates      : " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ (Ugen -> Int) -> [Ugen] -> [Char]
forall {a} {a}. (Show a, Ord a) => (a -> a) -> [a] -> [Char]
f Ugen -> Int
ugen_rate [Ugen]
us
      , [Char]
"unit generator set        : " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ ([[Char]] -> [[Char]]) -> [Char]
sq ([[Char]] -> [[Char]]
forall a. Eq a => [a] -> [a]
nub ([[Char]] -> [[Char]])
-> ([[Char]] -> [[Char]]) -> [[Char]] -> [[Char]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [[Char]] -> [[Char]]
forall a. Ord a => [a] -> [a]
sort)
      , [Char]
"unit generator sequence   : " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ ([[Char]] -> [[Char]]) -> [Char]
sq [[Char]] -> [[Char]]
forall a. a -> a
id
      ]

-- * Dump Ugens

-- | Pretty print Ugen in the manner of SynthDef>>dumpUgens.
ugen_dump_ugen_str :: [Sample] -> [Ugen] -> Ugen_Index -> Ugen -> String
ugen_dump_ugen_str :: [Sample] -> [Ugen] -> Int -> Ugen -> [Char]
ugen_dump_ugen_str [Sample]
c_sq [Ugen]
u_sq Int
ix Ugen
u =
  let in_brackets :: String -> String
      in_brackets :: [Char] -> [Char]
in_brackets [Char]
x = [Char] -> [Char] -> [Char]
forall r. PrintfType r => [Char] -> r
printf [Char]
"[%s]" [Char]
x
      input_pp :: Input -> t
input_pp (Input Int
i Int
j) =
        let ui :: Ugen
ui = [Ugen]
u_sq [Ugen] -> Int -> Ugen
forall a. Partial => [a] -> Int -> a
!! Int
i
        in if Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
0
            then
              if [Int] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length (Ugen -> [Int]
ugen_outputs Ugen
ui) Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
1
                then [Char] -> Int -> [Char] -> Int -> t
forall r. PrintfType r => [Char] -> r
printf [Char]
"%d_%s:%d" Int
i (Ugen -> [Char]
ugen_name_op Ugen
ui) Int
j
                else [Char] -> Int -> [Char] -> t
forall r. PrintfType r => [Char] -> r
printf [Char]
"%d_%s" Int
i (Ugen -> [Char]
ugen_name_op Ugen
ui)
            else [Char] -> Sample -> t
forall r. PrintfType r => [Char] -> r
printf [Char]
"%f" ([Sample]
c_sq [Sample] -> Int -> Sample
forall a. Partial => [a] -> Int -> a
!! Int
j)
      inputs_pp :: [Input] -> [Char]
inputs_pp = [Char] -> [Char]
in_brackets ([Char] -> [Char]) -> ([Input] -> [Char]) -> [Input] -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> [[Char]] -> [Char]
forall a. [a] -> [[a]] -> [a]
intercalate [Char]
"," ([[Char]] -> [Char]) -> ([Input] -> [[Char]]) -> [Input] -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Input -> [Char]) -> [Input] -> [[Char]]
forall a b. (a -> b) -> [a] -> [b]
map Input -> [Char]
forall {t}. PrintfType t => Input -> t
input_pp
  in [Char] -> Int -> [Char] -> [Char] -> [Char] -> [Char]
forall r. PrintfType r => [Char] -> r
printf [Char]
"%d_%s, %s, %s" Int
ix (Ugen -> [Char]
ugen_name_op Ugen
u) (Rate -> [Char]
forall a. Show a => a -> [Char]
show (Ugen -> Rate
ugen_rate_enum Ugen
u)) ([Input] -> [Char]
inputs_pp (Ugen -> [Input]
ugen_inputs Ugen
u))

-- | Print graphdef in format equivalent to SynthDef>>dumpUgens in SuperCollider
graphdef_dump_ugens_str :: Graphdef -> [String]
graphdef_dump_ugens_str :: Graphdef -> [[Char]]
graphdef_dump_ugens_str (Graphdef Name
_nm [Sample]
cs [(Control, Sample)]
_ks [Ugen]
us) = (Int -> Ugen -> [Char]) -> [Int] -> [Ugen] -> [[Char]]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith ([Sample] -> [Ugen] -> Int -> Ugen -> [Char]
ugen_dump_ugen_str [Sample]
cs [Ugen]
us) [Int
0 ..] [Ugen]
us

{- | 'putStrLn' of 'unlines' of 'graphdef_dump_ugens_str'

> import Sound.Sc3.Server.Graphdef
> import Sound.Sc3.Server.Graphdef.Io
> dir = "/home/rohan/sw/rsc3-disassembler/scsyndef/"
> pp nm = read_graphdef_file (dir ++ nm) >>= graphdef_dump_ugens
> pp "simple.scsyndef"
> pp "with-ctl.scsyndef"
> pp "mce.scsyndef"
> pp "mrg.scsyndef"
-}
graphdef_dump_ugens :: Graphdef -> IO ()
graphdef_dump_ugens :: Graphdef -> IO ()
graphdef_dump_ugens = [Char] -> IO ()
putStrLn ([Char] -> IO ()) -> (Graphdef -> [Char]) -> Graphdef -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [[Char]] -> [Char]
unlines ([[Char]] -> [Char])
-> (Graphdef -> [[Char]]) -> Graphdef -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Graphdef -> [[Char]]
graphdef_dump_ugens_str