-- Copyright 2017 Evan Laforge
-- This program is distributed under the terms of the GNU General Public
-- License 3.0, see COPYING or http://www.gnu.org/licenses/gpl-3.0.txt

-- | Low level binding to faust dsps, specialized for ones that generate audio.
module Synth.Faust.InstrumentC (
    PatchT(..), Patch, Instrument
    , Control
    -- * Patch
    , getPatches
    , imControls
    , ControlConfig(..)
    -- * Instrument
    , allocate, destroy
    , render
    -- ** state
    , getState, unsafeGetState, putState
) where
import qualified Data.List as List
import qualified Data.Map as Map
import qualified Data.Text as Text
import qualified Data.Vector.Storable as V

import qualified Util.Audio.Audio as Audio
import qualified Util.Lists as Lists

import qualified Synth.Faust.PatchC as PatchC
import qualified Synth.Lib.Checkpoint as Checkpoint
import qualified Synth.Shared.Control as Control

import qualified Ui.Id as Id

import           ForeignC
import           Global


data PatchT ptr cptr = Patch {
    forall ptr cptr. PatchT ptr cptr -> Text
_name :: !Text
    , forall ptr cptr. PatchT ptr cptr -> Text
_doc :: !Text
    -- | Corresponds to 'Instrument.Common.Triggered' flag.
    , forall ptr cptr. PatchT ptr cptr -> Bool
_impulseGate :: !Bool
    , forall ptr cptr. PatchT ptr cptr -> Maybe Text
_elementFrom :: !(Maybe Text)
    -- | An allocated Instrument has pointers to set control values, but a
    -- Patch doesn't.
    , forall ptr cptr.
PatchT ptr cptr -> Map Control (cptr, ControlConfig)
_controls :: !(Map Control (cptr, ControlConfig))
    -- | Inputs are positional, so it's important to preserve their order.
    -- TODO: Inputs should also have an Element.
    , forall ptr cptr. PatchT ptr cptr -> [(Control, ControlConfig)]
_inputControls :: ![(Control.Control, ControlConfig)]
    , forall ptr cptr. PatchT ptr cptr -> Int
_outputs :: !Int
    , forall ptr cptr. PatchT ptr cptr -> ptr
_ptr :: !ptr
    } deriving (Int -> PatchT ptr cptr -> ShowS
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall ptr cptr.
(Show cptr, Show ptr) =>
Int -> PatchT ptr cptr -> ShowS
forall ptr cptr.
(Show cptr, Show ptr) =>
[PatchT ptr cptr] -> ShowS
forall ptr cptr. (Show cptr, Show ptr) => PatchT ptr cptr -> String
showList :: [PatchT ptr cptr] -> ShowS
$cshowList :: forall ptr cptr.
(Show cptr, Show ptr) =>
[PatchT ptr cptr] -> ShowS
show :: PatchT ptr cptr -> String
$cshow :: forall ptr cptr. (Show cptr, Show ptr) => PatchT ptr cptr -> String
showsPrec :: Int -> PatchT ptr cptr -> ShowS
$cshowsPrec :: forall ptr cptr.
(Show cptr, Show ptr) =>
Int -> PatchT ptr cptr -> ShowS
Show)

-- | A patch can be used to create 'Instrument's.
type Patch = PatchT PatchC.PatchP ()

-- | An allocated patch.
type Instrument = PatchT PatchC.InstrumentP (Ptr Float)

data ControlConfig = ControlConfig {
    ControlConfig -> Bool
_constant :: !Bool
    , ControlConfig -> Text
_description :: !Text
    } deriving (ControlConfig -> ControlConfig -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ControlConfig -> ControlConfig -> Bool
$c/= :: ControlConfig -> ControlConfig -> Bool
== :: ControlConfig -> ControlConfig -> Bool
$c== :: ControlConfig -> ControlConfig -> Bool
Eq, Int -> ControlConfig -> ShowS
[ControlConfig] -> ShowS
ControlConfig -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ControlConfig] -> ShowS
$cshowList :: [ControlConfig] -> ShowS
show :: ControlConfig -> String
$cshow :: ControlConfig -> String
showsPrec :: Int -> ControlConfig -> ShowS
$cshowsPrec :: Int -> ControlConfig -> ShowS
Show)

instance Pretty ControlConfig where
    pretty :: ControlConfig -> Text
pretty (ControlConfig Bool
constant Text
desc) =
        (if Bool
constant then Text
"(per-note constant): " else Text
"") forall a. Semigroup a => a -> a -> a
<> Text
desc

type Control = (Element, Control.Control)
type Element = Text


-- * Patch

-- | Get all patches and their names.
getPatches :: IO (Map Text (Either Text Patch))
getPatches :: IO (Map Text (Either Text Patch))
getPatches = do
    ([Text]
names, [PatchP]
patches) <- forall a b. [(a, b)] -> ([a], [b])
unzip forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO [(Text, PatchP)]
PatchC.patches
    [Map Text Text]
metas <- forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM PatchP -> IO (Map Text Text)
PatchC.getMetadata [PatchP]
patches
    [[(Control, Text)]]
uis <- forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM PatchP -> IO [(Control, Text)]
getUiControls [PatchP]
patches
    let inputs :: [Int]
inputs = forall a b. (a -> b) -> [a] -> [b]
map PatchP -> Int
PatchC.patchInputs [PatchP]
patches
        outputs :: [Int]
outputs = forall a b. (a -> b) -> [a] -> [b]
map PatchP -> Int
PatchC.patchOutputs [PatchP]
patches
    forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList forall a b. (a -> b) -> a -> b
$ forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Text
"effect-" `Text.isPrefixOf`) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a, b) -> a
fst) forall a b. (a -> b) -> a -> b
$
        forall a b. [a] -> [b] -> [(a, b)]
zip [Text]
names forall a b. (a -> b) -> a -> b
$
        forall a b c d e f g.
(a -> b -> c -> d -> e -> f -> g)
-> [a] -> [b] -> [c] -> [d] -> [e] -> [f] -> [g]
List.zipWith6 Text
-> Map Text Text
-> [(Control, Text)]
-> Int
-> Int
-> PatchP
-> Either Text Patch
makePatch [Text]
names [Map Text Text]
metas [[(Control, Text)]]
uis [Int]
inputs [Int]
outputs [PatchP]
patches

makePatch :: Text -> Map Text Text -> [(Control, Text)]
    -> Int -> Int -> PatchC.PatchP -> Either Text Patch
makePatch :: Text
-> Map Text Text
-> [(Control, Text)]
-> Int
-> Int
-> PatchP
-> Either Text Patch
makePatch Text
name Map Text Text
meta [(Control, Text)]
uis Int
inputs Int
outputs PatchP
ptr = forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first ((Text
name forall a. Semigroup a => a -> a -> a
<> Text
": ")<>) forall a b. (a -> b) -> a -> b
$ do
    (Text
doc, [(Control, ControlConfig)]
inputControls) <- Map Text Text -> Either Text (Text, [(Control, ControlConfig)])
parseMetadata Map Text Text
meta
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (forall (t :: * -> *) a. Foldable t => t a -> Int
length [(Control, ControlConfig)]
inputControls forall a. Eq a => a -> a -> Bool
== Int
inputs) forall a b. (a -> b) -> a -> b
$
        forall a b. a -> Either a b
Left forall a b. (a -> b) -> a -> b
$ Text
"input count " forall a. Semigroup a => a -> a -> a
<> forall a. Show a => a -> Text
showt Int
inputs
            forall a. Semigroup a => a -> a -> a
<> Text
" doesn't match inputControls: "
            forall a. Semigroup a => a -> a -> a
<> forall a. Pretty a => a -> Text
pretty (forall a b. (a -> b) -> [a] -> [b]
map forall a b. (a, b) -> a
fst [(Control, ControlConfig)]
inputControls)
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (Int
outputs forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Int
1, Int
2]) forall a b. (a -> b) -> a -> b
$
        forall a b. a -> Either a b
Left forall a b. (a -> b) -> a -> b
$ Text
"expected 1 or 2 outputs, got " forall a. Semigroup a => a -> a -> a
<> forall a. Show a => a -> Text
showt Int
outputs
    let dups :: [(Control, NonEmpty Control)]
dups = forall k a. Ord k => (a -> k) -> [a] -> [(a, NonEmpty a)]
Lists.findDups forall a. a -> a
id (forall a b. (a -> b) -> [a] -> [b]
map forall a b. (a, b) -> a
fst [(Control, ControlConfig)]
inputControls) in forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (forall (t :: * -> *) a. Foldable t => t a -> Bool
null [(Control, NonEmpty Control)]
dups) forall a b. (a -> b) -> a -> b
$
        forall a b. a -> Either a b
Left forall a b. (a -> b) -> a -> b
$ Text
"duplicate input names: " forall a. Semigroup a => a -> a -> a
<> forall a. Pretty a => a -> Text
pretty (forall a b. (a -> b) -> [a] -> [b]
map forall a b. (a, b) -> a
fst [(Control, NonEmpty Control)]
dups)
    forall (m :: * -> *) a.
Applicative m =>
Maybe a -> (a -> m ()) -> m ()
whenJust ([Control] -> Maybe Text
verifyControls (forall a b. (a -> b) -> [a] -> [b]
map forall a b. (a, b) -> a
fst [(Control, Text)]
uis)) forall a b. (a -> b) -> a -> b
$ \Text
err ->
        forall a b. a -> Either a b
Left forall a b. (a -> b) -> a -> b
$ Text
"controls " forall a. Semigroup a => a -> a -> a
<> forall a. Pretty a => a -> Text
pretty (forall a b. (a -> b) -> [a] -> [b]
map forall a b. (a, b) -> a
fst [(Control, Text)]
uis) forall a. Semigroup a => a -> a -> a
<> Text
": " forall a. Semigroup a => a -> a -> a
<> Text
err
    Bool
impulse <- case forall k a. Ord k => a -> k -> Map k a -> a
Map.findWithDefault Text
"" Text
"flags" Map Text Text
meta of
        Text
"" -> forall a b. b -> Either a b
Right Bool
False
        Text
"impulse-gate" -> forall a b. b -> Either a b
Right Bool
True
        Text
val -> forall a b. a -> Either a b
Left forall a b. (a -> b) -> a -> b
$ Text
"unknown flags, only 'impulse-gate' is supported: " forall a. Semigroup a => a -> a -> a
<> Text
val
    forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Patch
        { _name :: Text
_name = Text
name
        , _doc :: Text
_doc = Text
doc
        , _impulseGate :: Bool
_impulseGate = Bool
impulse
        , _elementFrom :: Maybe Text
_elementFrom = forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup Text
"element_from" Map Text Text
meta
        , _controls :: Map Control ((), ControlConfig)
_controls = forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList
            [ ((Text
elt, Control
control), ((), Bool -> Text -> ControlConfig
ControlConfig Bool
False Text
cdoc))
            | ((Text
elt, Control
control), Text
cdoc) <- [(Control, Text)]
uis
            ]
        , _inputControls :: [(Control, ControlConfig)]
_inputControls = [(Control, ControlConfig)]
inputControls
        , _outputs :: Int
_outputs = Int
outputs
        , _ptr :: PatchP
_ptr = PatchP
ptr
        }

-- | Map supported controls to ControlConfig.  This is for the Im.Patch.
imControls :: PatchT ptr cptr -> Map Control.Control ControlConfig
imControls :: forall ptr cptr. PatchT ptr cptr -> Map Control ControlConfig
imControls PatchT ptr cptr
patch =
    -- Control.gate is generated internally, and everyone gets Control.vol.
    forall k a. Ord k => k -> Map k a -> Map k a
Map.delete Control
Control.gate forall a b. (a -> b) -> a -> b
$ forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert Control
Control.volume ControlConfig
vol forall a b. (a -> b) -> a -> b
$
        forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList (forall ptr cptr. PatchT ptr cptr -> [(Control, ControlConfig)]
_inputControls PatchT ptr cptr
patch) forall a. Semigroup a => a -> a -> a
<> Map Control ControlConfig
ui_controls
    where
    ui_controls :: Map Control ControlConfig
ui_controls = forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList forall a b. (a -> b) -> a -> b
$ do
        (Control
control, controls :: NonNull (Control, (cptr, ControlConfig))
controls@((Control
_, (cptr
_, ControlConfig
config)) : NonNull (Control, (cptr, ControlConfig))
_)) <- [(Control, NonNull (Control, (cptr, ControlConfig)))]
by_control
        let elts :: [Text]
elts = forall a. (a -> Bool) -> [a] -> [a]
filter (forall a. Eq a => a -> a -> Bool
/=Text
"") forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map (forall a b. (a, b) -> a
fst forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a, b) -> a
fst) NonNull (Control, (cptr, ControlConfig))
controls
        forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ (Control
control,) forall a b. (a -> b) -> a -> b
$ ControlConfig
config
            { _description :: Text
_description =
                (if forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Text]
elts then Text
""
                    else Text
"elements: [" forall a. Semigroup a => a -> a -> a
<> Text -> [Text] -> Text
Text.intercalate Text
", " [Text]
elts forall a. Semigroup a => a -> a -> a
<> Text
"], ")
                forall a. Semigroup a => a -> a -> a
<> ControlConfig -> Text
_description ControlConfig
config
            }
    by_control :: [(Control, NonNull (Control, (cptr, ControlConfig)))]
by_control = forall key a. Ord key => (a -> key) -> [a] -> [(key, [a])]
Lists.keyedGroupSort (forall a b. (a, b) -> b
snd forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a, b) -> a
fst) forall a b. (a -> b) -> a -> b
$
        forall k a. Map k a -> [(k, a)]
Map.toList forall a b. (a -> b) -> a -> b
$ forall ptr cptr.
PatchT ptr cptr -> Map Control (cptr, ControlConfig)
_controls PatchT ptr cptr
patch
    vol :: ControlConfig
vol = Bool -> Text -> ControlConfig
ControlConfig Bool
False Text
"Instrument volume, handled by faust-im."

verifyControls :: [Control] -> Maybe Text
verifyControls :: [Control] -> Maybe Text
verifyControls [Control]
controls
    | Bool -> Bool
not (forall (t :: * -> *) a. Foldable t => t a -> Bool
null [(Control, NonEmpty Control)]
dups) = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ Text
"duplicate (element, control): " forall a. Semigroup a => a -> a -> a
<> forall a. Pretty a => a -> Text
pretty [(Control, NonEmpty Control)]
dups
    | Bool
otherwise = case forall a b. Ord a => [(a, b)] -> [(a, NonNull b)]
Lists.groupFst forall a b. (a -> b) -> a -> b
$ forall a. (a -> Bool) -> [a] -> [a]
filter ((forall a. Eq a => a -> a -> Bool
/=Text
"") forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a, b) -> a
fst) [Control]
controls of
        [] -> forall a. Maybe a
Nothing
        (Text
_, NonNull Control
cs1) : [(Text, NonNull Control)]
rest -> case forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
List.find ((forall a. Eq a => a -> a -> Bool
/=NonNull Control
cs1) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a, b) -> b
snd) [(Text, NonNull Control)]
rest of
            Maybe (Text, NonNull Control)
Nothing -> forall a. Maybe a
Nothing
            Just (Text
elt2, NonNull Control
cs2) -> forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ Text
"every element should have "
                forall a. Semigroup a => a -> a -> a
<> forall a. Pretty a => a -> Text
pretty NonNull Control
cs1 forall a. Semigroup a => a -> a -> a
<> Text
" but " forall a. Semigroup a => a -> a -> a
<> Text
elt2 forall a. Semigroup a => a -> a -> a
<> Text
" has " forall a. Semigroup a => a -> a -> a
<> forall a. Pretty a => a -> Text
pretty NonNull Control
cs2
    where dups :: [(Control, NonEmpty Control)]
dups = forall k a. Ord k => (a -> k) -> [a] -> [(a, NonEmpty a)]
Lists.findDups forall a. a -> a
id [Control]
controls

parseMetadata :: Map Text Text
    -> Either Text (Text, [(Control.Control, ControlConfig)])
parseMetadata :: Map Text Text -> Either Text (Text, [(Control, ControlConfig)])
parseMetadata Map Text Text
meta = (Map Text Text -> Text
PatchC.parseDescription Map Text Text
meta,) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Map Text Text -> Either Text [(Control, ControlConfig)]
metadataControls Map Text Text
meta

-- | Get control names from the faust metadata.
--
-- The convention is that controls are declared via:
--
-- > declare control#_name "Doc."
--
-- The # is so they sort in the same order as the input signals to which they
-- correspond.  If the Doc starts with constant:, this is a constant control,
-- sampled at the note attack time.
metadataControls :: Map Text Text
    -> Either Text [(Control.Control, ControlConfig)]
    -- ^ this is in the declaration order, which should be the same as the dsp
    -- input order
metadataControls :: Map Text Text -> Either Text [(Control, ControlConfig)]
metadataControls = forall {b}.
Pretty b =>
[(Control, b)] -> Either Text [(Control, b)]
check forall (m :: * -> *) b c a.
Monad m =>
(b -> m c) -> (a -> m b) -> a -> m c
<=< forall (m :: * -> *) a b.
Monad m =>
(a -> m (Maybe b)) -> [a] -> m [b]
mapMaybeM (Text, Text) -> Either Text (Maybe (Control, ControlConfig))
parse forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall k a. Map k a -> [(k, a)]
Map.toAscList
    where
    check :: [(Control, b)] -> Either Text [(Control, b)]
check [(Control, b)]
controls
        | Control
Control.volume forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` forall a b. (a -> b) -> [a] -> [b]
map forall a b. (a, b) -> a
fst [(Control, b)]
controls =
            forall a b. a -> Either a b
Left forall a b. (a -> b) -> a -> b
$ forall a. Pretty a => a -> Text
pretty Control
Control.volume forall a. Semigroup a => a -> a -> a
<> Text
" shadowed by internal use"
        | forall (t :: * -> *) a. Foldable t => t a -> Bool
null [((Control, b), [(Control, b)])]
dups = forall a b. b -> Either a b
Right [(Control, b)]
controls
        | Bool
otherwise = forall a b. a -> Either a b
Left forall a b. (a -> b) -> a -> b
$ Text
"duplicate controls: "
            forall a. Semigroup a => a -> a -> a
<> Text -> [Text] -> Text
Text.intercalate Text
", " (forall a b. (a -> b) -> [a] -> [b]
map (forall a. Pretty a => a -> Text
pretty forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a, b) -> a
fst) [((Control, b), [(Control, b)])]
dups)
        where ([(Control, b)]
_, [((Control, b), [(Control, b)])]
dups) = forall k a. Ord k => (a -> k) -> [a] -> ([a], [(a, [a])])
Lists.partitionDups forall a b. (a, b) -> a
fst [(Control, b)]
controls
    parse :: (Text, Text) -> Either Text (Maybe (Control, ControlConfig))
parse (Text
c, Text
desc)
        | Just Text
rest <- Text -> Text -> Maybe Text
Text.stripPrefix Text
"control" Text
c =
            let stripped :: Text
stripped = Int -> Text -> Text
Text.drop Int
1 forall a b. (a -> b) -> a -> b
$ (Char -> Bool) -> Text -> Text
Text.dropWhile (forall a. Eq a => a -> a -> Bool
/=Char
'_') Text
rest
            in if Text -> Bool
Id.valid_symbol Text
stripped
                then forall a b. b -> Either a b
Right forall a b. (a -> b) -> a -> b
$
                    forall a. a -> Maybe a
Just (Text -> Control
Control.Control Text
stripped, Text -> ControlConfig
parseControlText Text
desc)
                else forall a b. a -> Either a b
Left forall a b. (a -> b) -> a -> b
$ Text
"invalid control name: " forall a. Semigroup a => a -> a -> a
<> Text
c
        | Bool
otherwise = forall a b. b -> Either a b
Right forall a. Maybe a
Nothing

parseControlText :: Text -> ControlConfig
parseControlText :: Text -> ControlConfig
parseControlText Text
desc
    | Just Text
desc <- Text -> Text -> Maybe Text
Text.stripPrefix Text
"constant:" Text
desc = Bool -> Text -> ControlConfig
ControlConfig Bool
True Text
desc
    | Bool
otherwise = Bool -> Text -> ControlConfig
ControlConfig Bool
False Text
desc

getUiControls :: PatchC.PatchP -> IO [(Control, Text)]
getUiControls :: PatchP -> IO [(Control, Text)]
getUiControls PatchP
patch = forall a b. (a -> b) -> [a] -> [b]
map (forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first ([Text], Control) -> Control
makeControl) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> PatchP -> IO [(([Text], Control), Text)]
PatchC.getUiControls PatchP
patch

makeControl :: ([Text], Control.Control) -> Control
makeControl :: ([Text], Control) -> Control
makeControl = forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first forall a b. (a -> b) -> a -> b
$ Text -> [Text] -> Text
Text.intercalate Text
"."
    forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Text
"_" `Text.isPrefixOf`)) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Int -> [a] -> [a]
drop Int
1
    -- The first path component is always the patch name, so I don't need it.
    -- underscore prefixed controls are used for UI organization, and are not
    -- the element.

-- * Instrument

allocate :: Patch -> IO Instrument
allocate :: Patch -> IO Instrument
allocate Patch
patch = do
    (InstrumentP
ptr, [(([Text], Control), Ptr Float)]
controls) <- PatchP -> IO (InstrumentP, [(([Text], Control), Ptr Float)])
PatchC.allocate (forall ptr cptr. PatchT ptr cptr -> ptr
_ptr Patch
patch)
    forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Patch
patch
        { _ptr :: InstrumentP
_ptr = InstrumentP
ptr
        , _controls :: Map Control (Ptr Float, ControlConfig)
_controls = forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList
            [ (Control
control, (Ptr Float
cptr, Control -> ControlConfig
getConfig Control
control))
            | (Control
control, Ptr Float
cptr) <- forall a b. (a -> b) -> [a] -> [b]
map (forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first ([Text], Control) -> Control
makeControl) [(([Text], Control), Ptr Float)]
controls
            ]
        }
    where
    -- A Nothing means getUiControls returned different controls than it did
    -- when the 'Patch' was constructed, which should not happen.
    getConfig :: Control -> ControlConfig
getConfig Control
c = forall b a. b -> (a -> b) -> Maybe a -> b
maybe (Bool -> Text -> ControlConfig
ControlConfig Bool
False Text
"") forall a b. (a, b) -> b
snd forall a b. (a -> b) -> a -> b
$
        forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup Control
c (forall ptr cptr.
PatchT ptr cptr -> Map Control (cptr, ControlConfig)
_controls Patch
patch)

destroy :: Instrument -> IO ()
destroy :: Instrument -> IO ()
destroy = InstrumentP -> IO ()
PatchC.c_faust_destroy forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall ptr cptr. PatchT ptr cptr -> ptr
_ptr

-- | Render chunk of time and return samples.
render :: Audio.Frames -> Audio.Frames -> Instrument
    -> [(Ptr Float, Audio.Block)]
    -> [V.Vector Float] -- ^ Input signals.  The length must be equal to the
    -- the patchInputs, and each vector must have the same length.
    -> IO [V.Vector Float] -- ^ one block of samples for each output channel
render :: Frames
-> Frames
-> Instrument
-> [(Ptr Float, Block)]
-> [Vector Float]
-> IO [Vector Float]
render Frames
controlSize Frames
controlsPerBlock Instrument
inst =
    Frames
-> Frames
-> InstrumentP
-> [(Ptr Float, Block)]
-> [Vector Float]
-> IO [Vector Float]
PatchC.render Frames
controlSize Frames
controlsPerBlock (forall ptr cptr. PatchT ptr cptr -> ptr
_ptr Instrument
inst)

-- * state

getState :: Instrument -> IO Checkpoint.State
getState :: Instrument -> IO State
getState = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ByteString -> State
Checkpoint.State forall b c a. (b -> c) -> (a -> b) -> a -> c
. InstrumentP -> IO ByteString
PatchC.getState forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall ptr cptr. PatchT ptr cptr -> ptr
_ptr

-- | 'getState', but without copying, if you promise to finish with the State
-- before you call 'render', which will change it.
unsafeGetState :: Instrument -> IO Checkpoint.State
unsafeGetState :: Instrument -> IO State
unsafeGetState = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ByteString -> State
Checkpoint.State forall b c a. (b -> c) -> (a -> b) -> a -> c
. InstrumentP -> IO ByteString
PatchC.unsafeGetState forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall ptr cptr. PatchT ptr cptr -> ptr
_ptr

putState :: Instrument -> Checkpoint.State -> IO ()
putState :: Instrument -> State -> IO ()
putState Instrument
inst (Checkpoint.State ByteString
state) =
    ByteString -> Text -> InstrumentP -> IO ()
PatchC.putState ByteString
state (forall ptr cptr. PatchT ptr cptr -> Text
_name Instrument
inst) (forall ptr cptr. PatchT ptr cptr -> ptr
_ptr Instrument
inst)