-- | Nrt from Ugen
module Sound.Sc3.Server.Nrt.Ugen where

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

import qualified Sound.Sc3.Common.Rate as Rate
import qualified Sound.Sc3.Server.Command.Plain as Server.Command
import qualified Sound.Sc3.Server.Enum as Server.Enum
import qualified Sound.Sc3.Server.Graphdef as Graphdef
import qualified Sound.Sc3.Server.Graphdef.Binary as Graphdef.Binary
import qualified Sound.Sc3.Server.Nrt as Nrt
import qualified Sound.Sc3.Server.Nrt.Render as Nrt.Render
import qualified Sound.Sc3.Server.Synthdef as Synthdef
import qualified Sound.Sc3.Ugen.Bindings.Db as Ugen.Binding
import qualified Sound.Sc3.Ugen.Ugen as Ugen

nrt_encoded_graphdef_rec :: Osc.Time -> Osc.Blob -> Nrt.Nrt
nrt_encoded_graphdef_rec :: Time -> Blob -> Nrt
nrt_encoded_graphdef_rec Time
dur Blob
graphdef =
  let m0 :: Message
m0 = Blob -> Message
Server.Command.d_recv_bytes Blob
graphdef
      m1 :: Message
m1 = String -> Synth_Id -> AddAction -> Synth_Id -> Message
Server.Command.s_new0 String
"Anonymous" Synth_Id
1 AddAction
Server.Enum.AddToHead Synth_Id
0
  in [BundleOf Message] -> Nrt
Nrt.Nrt [Time -> [Message] -> BundleOf Message
forall t. Time -> [t] -> BundleOf t
Osc.bundle Time
0 [Message
m0, Message
m1], Time -> [Message] -> BundleOf Message
forall t. Time -> [t] -> BundleOf t
Osc.bundle Time
dur [Message
Server.Command.nrt_end]]

nrt_graphdef_rec :: Osc.Time -> Graphdef.Graphdef -> Nrt.Nrt
nrt_graphdef_rec :: Time -> Graphdef -> Nrt
nrt_graphdef_rec Time
dur Graphdef
graphdef = Time -> Blob -> Nrt
nrt_encoded_graphdef_rec Time
dur (Graphdef -> Blob
Graphdef.Binary.encode_graphdef Graphdef
graphdef)

nrt_syndef_rec :: Osc.Time -> Synthdef.Synthdef -> Nrt.Nrt
nrt_syndef_rec :: Time -> Synthdef -> Nrt
nrt_syndef_rec Time
dur Synthdef
syndef = Time -> Graphdef -> Nrt
nrt_graphdef_rec Time
dur (Synthdef -> Graphdef
Synthdef.synthdef_to_graphdef Synthdef
syndef)

{- | Make Nrt score that runs Ugen for Time seconds to output bus zero.
If Ugen is at ControlRate insert 'k2a' Ugen.
-}
nrt_ugen_rec :: Osc.Time -> Ugen.Ugen -> Nrt.Nrt
nrt_ugen_rec :: Time -> Ugen -> Nrt
nrt_ugen_rec Time
dur Ugen
ugen =
  let ugen' :: Ugen
ugen' =
        case Ugen -> Rate
Ugen.rateOf Ugen
ugen of
          Rate
Rate.AudioRate -> Ugen
ugen
          Rate
Rate.ControlRate -> Ugen -> Ugen
Ugen.Binding.k2a Ugen
ugen
          Rate
_ -> String -> Ugen
forall a. HasCallStack => String -> a
error String
"nrt_ugen_rec: rate?"
  in Time -> Synthdef -> Nrt
nrt_syndef_rec Time
dur (String -> Ugen -> Synthdef
Synthdef.synthdef String
"Anonymous" (Ugen -> Ugen -> Ugen
Ugen.Binding.out Ugen
0 Ugen
ugen'))

-- | (osc-file, sound-file, sample-rate, sample-format, scsynth-options)
type Nrt_Opt = (FilePath, FilePath, Int, Server.Enum.SampleFormat, [String])

nrt_encoded_graphdef_render :: Nrt_Opt -> Osc.Time -> Int -> Osc.Blob -> IO ()
nrt_encoded_graphdef_render :: Nrt_Opt -> Time -> Synth_Id -> Blob -> IO ()
nrt_encoded_graphdef_render (String
osc_fn, String
sf_fn, Synth_Id
sample_rate, SampleFormat
fmt, [String]
opt) Time
dur Synth_Id
nc Blob
syndef = do
  let sc :: Nrt
sc = Time -> Blob -> Nrt
nrt_encoded_graphdef_rec Time
dur Blob
syndef
  Nrt_Render_Plain -> Nrt -> IO ()
Nrt.Render.nrt_render_plain (String
osc_fn, String
sf_fn, Synth_Id
nc, Synth_Id
sample_rate, SampleFormat
fmt, [String]
opt) Nrt
sc

nrt_syndef_render :: Nrt_Opt -> Osc.Time -> Int -> Synthdef.Synthdef -> IO ()
nrt_syndef_render :: Nrt_Opt -> Time -> Synth_Id -> Synthdef -> IO ()
nrt_syndef_render (String
osc_fn, String
sf_fn, Synth_Id
sample_rate, SampleFormat
fmt, [String]
opt) Time
dur Synth_Id
nc Synthdef
syndef = do
  let sc :: Nrt
sc = Time -> Synthdef -> Nrt
nrt_syndef_rec Time
dur Synthdef
syndef
  Nrt_Render_Plain -> Nrt -> IO ()
Nrt.Render.nrt_render_plain (String
osc_fn, String
sf_fn, Synth_Id
nc, Synth_Id
sample_rate, SampleFormat
fmt, [String]
opt) Nrt
sc

{- | 'nrt_render_plain' of 'ugen_rec_nrt'.
The number of channels is equal to the degree of the Ugen.
-}
nrt_ugen_render :: Nrt_Opt -> Osc.Time -> Ugen.Ugen -> IO ()
nrt_ugen_render :: Nrt_Opt -> Time -> Ugen -> IO ()
nrt_ugen_render (String
osc_fn, String
sf_fn, Synth_Id
sample_rate, SampleFormat
fmt, [String]
opt) Time
dur Ugen
u = do
  let sc :: Nrt
sc = Time -> Ugen -> Nrt
nrt_ugen_rec Time
dur Ugen
u
      nc :: Synth_Id
nc = [Ugen] -> Synth_Id
forall a. [a] -> Synth_Id
forall (t :: * -> *) a. Foldable t => t a -> Synth_Id
length (Ugen -> [Ugen]
Ugen.mceChannels Ugen
u)
  Nrt_Render_Plain -> Nrt -> IO ()
Nrt.Render.nrt_render_plain (String
osc_fn, String
sf_fn, Synth_Id
nc, Synth_Id
sample_rate, SampleFormat
fmt, [String]
opt) Nrt
sc