-- | Generate UGen binding functions from DB. module Sound.SC3.UGen.DB.Bindings where import Data.List import Data.Maybe import Sound.SC3.UGen.Name {- hsc3 -} import Text.Printf import Sound.SC3.UGen.DB.Record -- > import Sound.SC3.UGen.DB -- > import Sound.SC3.UGen.DB.Data -- > import Sound.SC3.UGen.DB.Rename -- > map ugen_name (filter (not . ugen_mce_sane) ugenDB) == [] ugen_mce_sane :: U -> Bool ugen_mce_sane u = case ugen_mce_input u of Just n -> n == length (ugen_inputs u) - 1 Nothing -> True -- > fmap u_input_names (uLookup "SinOsc") -- > fmap u_input_names (uLookup "BufRd") u_input_names :: U -> [String] u_input_names = map input_name . ugen_inputs unenumerator :: String -> String unenumerator en = case en of "Loop" -> "from_loop" "Interpolation" -> "from_interpolation" "DoneAction" -> "from_done_action" "Warp" -> "from_warp" _ -> error "unenumerator" input_name_proc :: I -> String input_name_proc i = let nm = input_name i in case input_enumeration i of Just en -> printf "%s %s" (unenumerator en) nm Nothing -> nm u_input_names_proc :: U -> [String] u_input_names_proc = map input_name_proc . ugen_inputs -- > about ('[',']') "a,b" == "[a,b]" about :: (a, a) -> [a] -> [a] about (p,q) s = p : s ++ [q] -- > brckt "a,b" == "[a,b]" brckt :: String -> String brckt = about ('[',']') quote :: [Char] -> [Char] quote = about ('"','"') -- > ppl_space ["freq","phase"] == "freq phase" ppl_space :: [String] -> String ppl_space = unwords' -- > ppl_list ["freq","phase"] == "[freq,phase]" ppl_list :: [String] -> String ppl_list = brckt . intercalate "," -- | Variant that 'delete's empty inputs, useful for pretty printing. -- -- > unwords ["a","","b"] == "a b" -- > unwords' ["a","","b"] == "a b" unwords' :: [String] -> String unwords' = unwords . filter (not . null) -- > fmap u_gen_type_sig (uLookup "Blip") -- > fmap u_gen_type_sig (uLookup "BufRd") -- > fmap u_gen_type_sig (uLookup "Resonz") -- > fmap u_gen_type_sig (uLookup "BrownNoise") u_gen_type_sig :: U -> [String] u_gen_type_sig u = let i = ugen_inputs u i_sig = map (fromMaybe "UGen" . input_enumeration) i nm_h = ugen_name u o = case ugen_outputs u of Left _ -> "" -- printf "{- nc=%d -}" k Right _ -> "Int ->" r = if isNothing (ugen_filter u) then "Rate ->" else "" -- "{- filter -}" i_sig' = intercalate " -> " i_sig arr = if null i then "" else "->" in [nm_h,"::",o,r,i_sig',arr,"UGen"] -- > fmap u_outputs (uLookup "BufRd") == Just ("numChannels","numChannels") -- > fmap u_outputs (uLookup "SinOsc") == Just ("","1") u_outputs :: U -> (String,String) u_outputs u = case ugen_outputs u of Left n -> ("",show n) Right _ -> ("numChannels","numChannels") -- > fmap u_gen_osc_f (uLookup "Blip") -- > fmap u_gen_osc_f (uLookup "BufRd") u_gen_osc_f :: U -> [String] u_gen_osc_f u = let nm_h = ugen_name u nm = toSC3Name nm_h i_s = ppl_space (u_input_names u) i_l = ppl_list (u_input_names_proc u) r = ppl_list (map show (ugen_operating_rates u)) (o_lhs,o_rhs) = u_outputs u in [nm_h,o_lhs,"rate",i_s,"= mkOscR",r,"rate",quote nm,i_l,o_rhs] -- > fmap u_gen_filter_f (uLookup "Resonz") u_gen_filter_f :: U -> [String] u_gen_filter_f u = let nm_h = ugen_name u nm = toSC3Name nm_h i = u_input_names u i_s = ppl_space i i_l = ppl_list i (o_lhs,o_rhs) = u_outputs u in [nm_h,o_lhs,i_s,"= mkFilter",quote nm,i_l,o_rhs] -- > fmap u_gen_binding (uLookup "LFGauss") -- > fmap (u_gen_binding . u_rename) (uLookup "In") -- > let b = map (u_gen_binding . u_rename_db ugenDB) ugenDB -- > writeFile "/tmp/bind-sc3.hs" (unlines (intercalate [""] b)) u_gen_binding :: U -> [String] u_gen_binding u = let c = ["-- |",ugen_summary u] s = u_gen_type_sig u b = case ugen_filter u of Just _ -> u_gen_filter_f u _ -> u_gen_osc_f u in map unwords' [c,s,b]