packages feed

hsc3-rec-0.14: mk/build.hs

import Data.Char
import Sound.SC3.UGen.Rate {- hsc3 -}
import qualified Sound.SC3.UGen.DB.Data as D {- hsc3-db -}
import qualified Sound.SC3.UGen.DB.Record as D
import qualified Sound.SC3.UGen.DB.Rename as D
import System.FilePath {- filepath -}
import Text.Printf

-- True if the unit generator can operate at multiple rates, in which
-- case the record will require a rate field.
needs_rate :: D.U -> Bool
needs_rate u = length (D.ugen_operating_rates u) > 1

-- In the case of one input rate use that instead of default rate,
-- which can be innacurate (see pitch for example).
fixed_rate :: D.U -> Rate
fixed_rate u =
    case D.ugen_operating_rates u of
      [r] -> r
      [] -> D.ugen_default_rate u
      _ -> undefined

--u_input_nm u k = D.input_name (D.ugen_inputs u !! k)

-- List of field names and types.
inputs_of :: D.U -> [(String, String)]
inputs_of u =
    let is = D.ugen_inputs u
        bs = zip (map D.input_name is) (repeat "S.UGen")
    in if needs_rate u
       then ("rate", "S.Rate") : bs
       else bs

-- Append a character to each but the last string.
with_char :: Char -> [String] -> [String]
with_char c l =
    case l of
      x:y:xs -> (x ++ [c]) : with_char c (y:xs)
      _ -> l

with_comma :: [String] -> [String]
with_comma = with_char ','

with_space :: [String] -> [String]
with_space = with_char ' '

downcase_first_char :: String -> String
downcase_first_char s =
    case s of
      [] -> []
      x:xs -> toLower x : xs

-- Construct the parameter record.
gen_param :: D.U -> [String]
gen_param u =
    let n = D.ugen_name u
        pre = [printf "data %s = %s {" n n]
        post = ["  } deriving (Show)"]
        f (nm, ty) = printf "  %s :: %s" nm ty
    in pre ++ with_comma (map f (inputs_of u)) ++ post

-- Construct a default instance of the parameter structure.
gen_defaults :: D.U -> [String]
gen_defaults u =
    let (D.U n _ r _ is _ _ _) = u
        nm = D.rename_ugen (downcase_first_char n)
        pre = [ printf "%s :: %s" nm n
              , printf "%s = %s {" nm n]
        post = [ "  }" ]
        opt = if needs_rate u then [printf "  rate = S.%s," (show r)] else []
        f i = printf "  %s = %f" (D.input_name i) (D.input_default i)
    in pre ++ opt ++ with_comma (map f is) ++ post

-- Generate a list of variable names (a,b..)
var_names :: Int -> [String]
var_names n = map (: "'") (take n ['a'..])

-- Generate the constructor for the unit generator.
gen_cons :: D.U -> [String]
gen_cons u =
    let (D.U n _ _ _ is _ o _) = u
        xs = var_names (length is)
        nr = needs_rate u
        l_opt = if nr then "r" else ""
        r_opt = if nr then "r" else printf "S.%s" (show (fixed_rate u))
        o' = case o of
               Left x -> show x
               Right _ -> "undefined"
    in [ printf "mk%s :: %s -> S.UGen" n n
       , printf "mk%s (%s %s %s) = S.mkOsc %s \"%s\" [%s] %s"
                n
                n
                l_opt
                (concat (with_space xs))
                r_opt
                n
                (concat (with_comma xs))
                o']

-- Generate instance of the Make class.
gen_make :: D.U -> [String]
gen_make u =
    let n = D.ugen_name u
    in [ printf "instance Make %s where" n
       , printf "  ugen = mk%s" n ]

-- Path to write files to.
sc3_ugen_dir :: FilePath
sc3_ugen_dir = "Sound" </> "SC3" </> "UGen"

-- Write module for a unit generator.
write_module :: D.U -> IO ()
write_module u =
    let n = D.ugen_name u
        m = [ printf "-- | %s" (D.ugen_summary u)
            , printf "module Sound.SC3.UGen.Record.%s where" n
            , "import qualified Sound.SC3.UGen as S"
            , "import Sound.SC3.UGen.Record" ]
        p = gen_param u
        d = gen_defaults u
        c = gen_cons u
        i = gen_make u
        fn = sc3_ugen_dir </> "Record" </> n <.> ".hs"
    in writeFile fn (unlines (m ++ p ++ d ++ c ++ i))

main :: IO ()
main = do
  let us = filter (not . null . D.ugen_inputs) D.ugenDB
  mapM_ write_module us

{-
gen_module_clause :: [D.U] -> [String]
gen_module_clause us =
    let f u = printf "  module Sound.SC3.UGen.Record.%s" (D.ugen_name u)
        pre = ["{-# LANGUAGE DisambiguateRecordFields #-}"
              ,"module Sound.SC3.UGen.Record.All ("]
        post = ["  ) where"]
    in pre ++ with_comma (map f us) ++ post

gen_imports :: [D.U] -> [String]
gen_imports =
    let f u = printf "import Sound.SC3.UGen.Record.%s" (D.ugen_name u)
    in map f

write_records :: [D.U] -> IO ()
write_records us =
    let s = unlines (gen_module_clause us ++ gen_imports us)
    in writeFile (sc3_ugen_dir </> "Record" </> "All" <.> "hs") s
-}