-- Copyright 2020 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

{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeApplications #-}
-- | Low level binding to patch_c.cc and the Patch c++ object, which represents
-- any faust dsp, both instruments and effects processors.
module Synth.Faust.PatchC where
import qualified Data.ByteString as ByteString
import qualified Data.ByteString.Unsafe as ByteString.Unsafe
import qualified Data.Map as Map
import qualified Data.Text as Text
import qualified Data.Vector.Storable as V

import qualified Foreign

import qualified Util.Audio.Audio as Audio
import qualified Util.FFI as FFI
import qualified Synth.Shared.Config as Config
import qualified Synth.Shared.Control as Control

import           ForeignC
import           Global


type PatchP = Ptr CConstPatchP
data CConstPatchP

-- | An allocated patch.
type InstrumentP = Ptr CPatchP
data CPatchP


patches :: IO [(Text, PatchP)]
patches :: IO [(Text, PatchP)]
patches = (Ptr (Ptr PatchP) -> IO [(Text, PatchP)]) -> IO [(Text, PatchP)]
forall a b. CStorable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr (Ptr PatchP) -> IO [(Text, PatchP)]) -> IO [(Text, PatchP)])
-> (Ptr (Ptr PatchP) -> IO [(Text, PatchP)]) -> IO [(Text, PatchP)]
forall a b. (a -> b) -> a -> b
$ \Ptr (Ptr PatchP)
patchpp -> do
    Int
count <- CInt -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (CInt -> Int) -> IO CInt -> IO Int
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Ptr (Ptr PatchP) -> IO CInt
c_faust_patches Ptr (Ptr PatchP)
patchpp
    [PatchP]
patches <- Int -> Ptr PatchP -> IO [PatchP]
forall a. CStorable a => Int -> Ptr a -> IO [a]
peekArray Int
count (Ptr PatchP -> IO [PatchP]) -> IO (Ptr PatchP) -> IO [PatchP]
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Ptr (Ptr PatchP) -> IO (Ptr PatchP)
forall a. CStorable a => Ptr a -> IO a
peek Ptr (Ptr PatchP)
patchpp
    [Text]
names <- (PatchP -> IO Text) -> [PatchP] -> IO [Text]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (Ptr CChar -> IO Text
FFI.peekCString (Ptr CChar -> IO Text)
-> (PatchP -> Ptr CChar) -> PatchP -> IO Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PatchP -> Ptr CChar
c_faust_name) [PatchP]
patches
    -- I use hyphens, but C doesn't allow them in names.
    [(Text, PatchP)] -> IO [(Text, PatchP)]
forall (m :: * -> *) a. Monad m => a -> m a
return ([(Text, PatchP)] -> IO [(Text, PatchP)])
-> [(Text, PatchP)] -> IO [(Text, PatchP)]
forall a b. (a -> b) -> a -> b
$ [Text] -> [PatchP] -> [(Text, PatchP)]
forall a b. [a] -> [b] -> [(a, b)]
zip ((Text -> Text) -> [Text] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map (Text -> Text -> Text -> Text
Text.replace Text
"_" Text
"-") [Text]
names) [PatchP]
patches

-- int faust_patches(const Patch ***patches);
foreign import ccall "faust_patches"
    c_faust_patches :: Ptr (Ptr PatchP) -> IO CInt

foreign import ccall "faust_name" c_faust_name :: PatchP -> CString

patchInputs, patchOutputs :: PatchP -> Int
patchInputs :: PatchP -> Int
patchInputs = CInt -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (CInt -> Int) -> (PatchP -> CInt) -> PatchP -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PatchP -> CInt
c_faust_num_inputs
patchOutputs :: PatchP -> Int
patchOutputs = CInt -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (CInt -> Int) -> (PatchP -> CInt) -> PatchP -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PatchP -> CInt
c_faust_num_outputs

instInputs, instOutputs :: InstrumentP -> Int
instInputs :: InstrumentP -> Int
instInputs = PatchP -> Int
patchInputs (PatchP -> Int) -> (InstrumentP -> PatchP) -> InstrumentP -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. InstrumentP -> PatchP
forall a b. Ptr a -> Ptr b
castPtr
instOutputs :: InstrumentP -> Int
instOutputs = PatchP -> Int
patchOutputs (PatchP -> Int) -> (InstrumentP -> PatchP) -> InstrumentP -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. InstrumentP -> PatchP
forall a b. Ptr a -> Ptr b
castPtr

foreign import ccall unsafe "faust_num_inputs"
    c_faust_num_inputs :: PatchP -> CInt
foreign import ccall unsafe "faust_num_outputs"
    c_faust_num_outputs :: PatchP -> CInt

getMetadata :: PatchP -> IO (Map Text Text)
getMetadata :: PatchP -> IO (Map Text Text)
getMetadata PatchP
patch = (Ptr (Ptr (Ptr CChar)) -> IO (Map Text Text)) -> IO (Map Text Text)
forall a b. CStorable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr (Ptr (Ptr CChar)) -> IO (Map Text Text))
 -> IO (Map Text Text))
-> (Ptr (Ptr (Ptr CChar)) -> IO (Map Text Text))
-> IO (Map Text Text)
forall a b. (a -> b) -> a -> b
$ \Ptr (Ptr (Ptr CChar))
keyspp -> (Ptr (Ptr (Ptr CChar)) -> IO (Map Text Text)) -> IO (Map Text Text)
forall a b. CStorable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr (Ptr (Ptr CChar)) -> IO (Map Text Text))
 -> IO (Map Text Text))
-> (Ptr (Ptr (Ptr CChar)) -> IO (Map Text Text))
-> IO (Map Text Text)
forall a b. (a -> b) -> a -> b
$ \Ptr (Ptr (Ptr CChar))
valuespp -> do
    Int
count <- CInt -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (CInt -> Int) -> IO CInt -> IO Int
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> PatchP -> Ptr (Ptr (Ptr CChar)) -> Ptr (Ptr (Ptr CChar)) -> IO CInt
c_faust_metadata PatchP
patch Ptr (Ptr (Ptr CChar))
keyspp Ptr (Ptr (Ptr CChar))
valuespp
    [(Text, Text)]
kvs <- [Text] -> [Text] -> [(Text, Text)]
forall a b. [a] -> [b] -> [(a, b)]
zip ([Text] -> [Text] -> [(Text, Text)])
-> IO [Text] -> IO ([Text] -> [(Text, Text)])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Int -> Ptr (Ptr CChar) -> IO [Text]
peekTexts Int
count (Ptr (Ptr CChar) -> IO [Text]) -> IO (Ptr (Ptr CChar)) -> IO [Text]
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Ptr (Ptr (Ptr CChar)) -> IO (Ptr (Ptr CChar))
forall a. CStorable a => Ptr a -> IO a
peek Ptr (Ptr (Ptr CChar))
keyspp)
        IO ([Text] -> [(Text, Text)]) -> IO [Text] -> IO [(Text, Text)]
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (Int -> Ptr (Ptr CChar) -> IO [Text]
peekTexts Int
count (Ptr (Ptr CChar) -> IO [Text]) -> IO (Ptr (Ptr CChar)) -> IO [Text]
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Ptr (Ptr (Ptr CChar)) -> IO (Ptr (Ptr CChar))
forall a. CStorable a => Ptr a -> IO a
peek Ptr (Ptr (Ptr CChar))
valuespp)
    Ptr (Ptr CChar) -> IO ()
forall a. Ptr a -> IO ()
free (Ptr (Ptr CChar) -> IO ()) -> IO (Ptr (Ptr CChar)) -> IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Ptr (Ptr (Ptr CChar)) -> IO (Ptr (Ptr CChar))
forall a. CStorable a => Ptr a -> IO a
peek Ptr (Ptr (Ptr CChar))
keyspp
    Ptr (Ptr CChar) -> IO ()
forall a. Ptr a -> IO ()
free (Ptr (Ptr CChar) -> IO ()) -> IO (Ptr (Ptr CChar)) -> IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Ptr (Ptr (Ptr CChar)) -> IO (Ptr (Ptr CChar))
forall a. CStorable a => Ptr a -> IO a
peek Ptr (Ptr (Ptr CChar))
valuespp
    Map Text Text -> IO (Map Text Text)
forall (m :: * -> *) a. Monad m => a -> m a
return (Map Text Text -> IO (Map Text Text))
-> Map Text Text -> IO (Map Text Text)
forall a b. (a -> b) -> a -> b
$ [(Text, Text)] -> Map Text Text
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList [(Text, Text)]
kvs

parseDescription :: Map Text Text -> Text
parseDescription :: Map Text Text -> Text
parseDescription Map Text Text
meta = Text -> [Text] -> Text
Text.intercalate Text
"\n" ([Text] -> Text) -> [Text] -> Text
forall a b. (a -> b) -> a -> b
$ (Text -> Bool) -> [Text] -> [Text]
forall a. (a -> Bool) -> [a] -> [a]
filter (Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
/=Text
"") ([Text] -> [Text]) -> [Text] -> [Text]
forall a b. (a -> b) -> a -> b
$
    Text -> Text -> Map Text Text -> Text
forall k a. Ord k => a -> k -> Map k a -> a
Map.findWithDefault Text
"" Text
"description" Map Text Text
meta
    Text -> [Text] -> [Text]
forall a. a -> [a] -> [a]
: (Text -> Text) -> [Text] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map (\Text
k -> Text -> (Text -> Text) -> Maybe Text -> Text
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Text
"" ((Text
k Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
": ")<>) (Maybe Text -> Text) -> Maybe Text -> Text
forall a b. (a -> b) -> a -> b
$ Text -> Map Text Text -> Maybe Text
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup Text
k Map Text Text
meta)
        [Text
"author", Text
"copyright", Text
"version", Text
"license"]

-- int faust_metadata(
--     const Patch *patch, const char ***keys, const char ***values);
foreign import ccall "faust_metadata"
    c_faust_metadata :: PatchP -> Ptr (Ptr CString) -> Ptr (Ptr CString)
        -> IO CInt

getUiControls :: PatchP -> IO [(([Text], Control.Control), Text)]
getUiControls :: PatchP -> IO [(([Text], Control), Text)]
getUiControls PatchP
patch = do
    (Int
count, Ptr (Ptr (Ptr CChar))
pathspp, Ptr (Ptr CChar)
controlsp, Ptr (Ptr CChar)
docsp) <-
        (Ptr (Ptr (Ptr (Ptr CChar)))
 -> IO
      (Int, Ptr (Ptr (Ptr CChar)), Ptr (Ptr CChar), Ptr (Ptr CChar)))
-> IO
     (Int, Ptr (Ptr (Ptr CChar)), Ptr (Ptr CChar), Ptr (Ptr CChar))
forall a b. CStorable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr (Ptr (Ptr (Ptr CChar)))
  -> IO
       (Int, Ptr (Ptr (Ptr CChar)), Ptr (Ptr CChar), Ptr (Ptr CChar)))
 -> IO
      (Int, Ptr (Ptr (Ptr CChar)), Ptr (Ptr CChar), Ptr (Ptr CChar)))
-> (Ptr (Ptr (Ptr (Ptr CChar)))
    -> IO
         (Int, Ptr (Ptr (Ptr CChar)), Ptr (Ptr CChar), Ptr (Ptr CChar)))
-> IO
     (Int, Ptr (Ptr (Ptr CChar)), Ptr (Ptr CChar), Ptr (Ptr CChar))
forall a b. (a -> b) -> a -> b
$ \Ptr (Ptr (Ptr (Ptr CChar)))
pathsppp -> (Ptr (Ptr (Ptr CChar))
 -> IO
      (Int, Ptr (Ptr (Ptr CChar)), Ptr (Ptr CChar), Ptr (Ptr CChar)))
-> IO
     (Int, Ptr (Ptr (Ptr CChar)), Ptr (Ptr CChar), Ptr (Ptr CChar))
forall a b. CStorable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr (Ptr (Ptr CChar))
  -> IO
       (Int, Ptr (Ptr (Ptr CChar)), Ptr (Ptr CChar), Ptr (Ptr CChar)))
 -> IO
      (Int, Ptr (Ptr (Ptr CChar)), Ptr (Ptr CChar), Ptr (Ptr CChar)))
-> (Ptr (Ptr (Ptr CChar))
    -> IO
         (Int, Ptr (Ptr (Ptr CChar)), Ptr (Ptr CChar), Ptr (Ptr CChar)))
-> IO
     (Int, Ptr (Ptr (Ptr CChar)), Ptr (Ptr CChar), Ptr (Ptr CChar))
forall a b. (a -> b) -> a -> b
$ \Ptr (Ptr (Ptr CChar))
controlspp -> (Ptr (Ptr (Ptr CChar))
 -> IO
      (Int, Ptr (Ptr (Ptr CChar)), Ptr (Ptr CChar), Ptr (Ptr CChar)))
-> IO
     (Int, Ptr (Ptr (Ptr CChar)), Ptr (Ptr CChar), Ptr (Ptr CChar))
forall a b. CStorable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr (Ptr (Ptr CChar))
  -> IO
       (Int, Ptr (Ptr (Ptr CChar)), Ptr (Ptr CChar), Ptr (Ptr CChar)))
 -> IO
      (Int, Ptr (Ptr (Ptr CChar)), Ptr (Ptr CChar), Ptr (Ptr CChar)))
-> (Ptr (Ptr (Ptr CChar))
    -> IO
         (Int, Ptr (Ptr (Ptr CChar)), Ptr (Ptr CChar), Ptr (Ptr CChar)))
-> IO
     (Int, Ptr (Ptr (Ptr CChar)), Ptr (Ptr CChar), Ptr (Ptr CChar))
forall a b. (a -> b) -> a -> b
$ \Ptr (Ptr (Ptr CChar))
docspp -> do
            CInt
count <- PatchP
-> Ptr (Ptr (Ptr (Ptr CChar)))
-> Ptr (Ptr (Ptr CChar))
-> Ptr (Ptr (Ptr CChar))
-> IO CInt
c_faust_controls PatchP
patch Ptr (Ptr (Ptr (Ptr CChar)))
pathsppp Ptr (Ptr (Ptr CChar))
controlspp Ptr (Ptr (Ptr CChar))
docspp
            (,,,) (CInt -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral CInt
count)
                (Ptr (Ptr (Ptr CChar))
 -> Ptr (Ptr CChar)
 -> Ptr (Ptr CChar)
 -> (Int, Ptr (Ptr (Ptr CChar)), Ptr (Ptr CChar), Ptr (Ptr CChar)))
-> IO (Ptr (Ptr (Ptr CChar)))
-> IO
     (Ptr (Ptr CChar)
      -> Ptr (Ptr CChar)
      -> (Int, Ptr (Ptr (Ptr CChar)), Ptr (Ptr CChar), Ptr (Ptr CChar)))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Ptr (Ptr (Ptr (Ptr CChar))) -> IO (Ptr (Ptr (Ptr CChar)))
forall a. CStorable a => Ptr a -> IO a
peek Ptr (Ptr (Ptr (Ptr CChar)))
pathsppp IO
  (Ptr (Ptr CChar)
   -> Ptr (Ptr CChar)
   -> (Int, Ptr (Ptr (Ptr CChar)), Ptr (Ptr CChar), Ptr (Ptr CChar)))
-> IO (Ptr (Ptr CChar))
-> IO
     (Ptr (Ptr CChar)
      -> (Int, Ptr (Ptr (Ptr CChar)), Ptr (Ptr CChar), Ptr (Ptr CChar)))
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Ptr (Ptr (Ptr CChar)) -> IO (Ptr (Ptr CChar))
forall a. CStorable a => Ptr a -> IO a
peek Ptr (Ptr (Ptr CChar))
controlspp IO
  (Ptr (Ptr CChar)
   -> (Int, Ptr (Ptr (Ptr CChar)), Ptr (Ptr CChar), Ptr (Ptr CChar)))
-> IO (Ptr (Ptr CChar))
-> IO
     (Int, Ptr (Ptr (Ptr CChar)), Ptr (Ptr CChar), Ptr (Ptr CChar))
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Ptr (Ptr (Ptr CChar)) -> IO (Ptr (Ptr CChar))
forall a. CStorable a => Ptr a -> IO a
peek Ptr (Ptr (Ptr CChar))
docspp
    -- pathsp is a null-terminated list of char*
    [Ptr (Ptr CChar)]
pathsp <- Int -> Ptr (Ptr (Ptr CChar)) -> IO [Ptr (Ptr CChar)]
forall a. CStorable a => Int -> Ptr a -> IO [a]
peekArray Int
count Ptr (Ptr (Ptr CChar))
pathspp
    [[Text]]
paths <- (Ptr (Ptr CChar) -> IO [Text]) -> [Ptr (Ptr CChar)] -> IO [[Text]]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM Ptr (Ptr CChar) -> IO [Text]
peekTexts0 [Ptr (Ptr CChar)]
pathsp
    (Ptr (Ptr CChar) -> IO ()) -> [Ptr (Ptr CChar)] -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ Ptr (Ptr CChar) -> IO ()
forall a. Ptr a -> IO ()
free [Ptr (Ptr CChar)]
pathsp
    Ptr (Ptr (Ptr CChar)) -> IO ()
forall a. Ptr a -> IO ()
free Ptr (Ptr (Ptr CChar))
pathspp

    -- Faust likes underscores, but I use hyphens for control names.
    [Control]
controls <- (Text -> Control) -> [Text] -> [Control]
forall a b. (a -> b) -> [a] -> [b]
map (Text -> Control
Control.Control (Text -> Control) -> (Text -> Text) -> Text -> Control
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text -> Text -> Text
Text.replace Text
"_" Text
"-") ([Text] -> [Control]) -> IO [Text] -> IO [Control]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>
        Int -> Ptr (Ptr CChar) -> IO [Text]
peekTexts Int
count Ptr (Ptr CChar)
controlsp
    Ptr (Ptr CChar) -> IO ()
forall a. Ptr a -> IO ()
free Ptr (Ptr CChar)
controlsp
    [Text]
docs <- Int -> Ptr (Ptr CChar) -> IO [Text]
peekTexts Int
count Ptr (Ptr CChar)
docsp
    (Ptr CChar -> IO ()) -> [Ptr CChar] -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ Ptr CChar -> IO ()
forall a. Ptr a -> IO ()
free ([Ptr CChar] -> IO ()) -> IO [Ptr CChar] -> IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Int -> Ptr (Ptr CChar) -> IO [Ptr CChar]
forall a. CStorable a => Int -> Ptr a -> IO [a]
peekArray Int
count Ptr (Ptr CChar)
docsp
    Ptr (Ptr CChar) -> IO ()
forall a. Ptr a -> IO ()
free Ptr (Ptr CChar)
docsp

    -- Lead with "_" to suppress the whole control.  But "_" was turned to "-".
    [(([Text], Control), Text)] -> IO [(([Text], Control), Text)]
forall (m :: * -> *) a. Monad m => a -> m a
return ([(([Text], Control), Text)] -> IO [(([Text], Control), Text)])
-> [(([Text], Control), Text)] -> IO [(([Text], Control), Text)]
forall a b. (a -> b) -> a -> b
$ ((([Text], Control), Text) -> Bool)
-> [(([Text], Control), Text)] -> [(([Text], Control), Text)]
forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not (Bool -> Bool)
-> ((([Text], Control), Text) -> Bool)
-> (([Text], Control), Text)
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Text
"-" `Text.isPrefixOf`) (Text -> Bool)
-> ((([Text], Control), Text) -> Text)
-> (([Text], Control), Text)
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Control -> Text
forall a. Pretty a => a -> Text
pretty (Control -> Text)
-> ((([Text], Control), Text) -> Control)
-> (([Text], Control), Text)
-> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([Text], Control) -> Control
forall a b. (a, b) -> b
snd (([Text], Control) -> Control)
-> ((([Text], Control), Text) -> ([Text], Control))
-> (([Text], Control), Text)
-> Control
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (([Text], Control), Text) -> ([Text], Control)
forall a b. (a, b) -> a
fst) ([(([Text], Control), Text)] -> [(([Text], Control), Text)])
-> [(([Text], Control), Text)] -> [(([Text], Control), Text)]
forall a b. (a -> b) -> a -> b
$
        [([Text], Control)] -> [Text] -> [(([Text], Control), Text)]
forall a b. [a] -> [b] -> [(a, b)]
zip ([[Text]] -> [Control] -> [([Text], Control)]
forall a b. [a] -> [b] -> [(a, b)]
zip [[Text]]
paths [Control]
controls) [Text]
docs


-- int faust_controls(Patch patch, const char ****out_paths,
--     const char ***out_controls, char ***out_docs)
foreign import ccall "faust_controls"
    c_faust_controls :: PatchP -> Ptr (Ptr (Ptr CString)) -> Ptr (Ptr CString)
        -> Ptr (Ptr CString) -> IO CInt

-- * Instrument

allocate :: PatchP -> IO (InstrumentP, [(([Text], Control.Control), Ptr Float)])
allocate :: PatchP -> IO (InstrumentP, [(([Text], Control), Ptr Float)])
allocate PatchP
patch = do
    InstrumentP
ptr <- PatchP -> CInt -> IO InstrumentP
c_faust_allocate PatchP
patch (Int -> CInt
FFI.c_int Int
Config.samplingRate)
    [Ptr Float]
cptrs <- (Ptr (Ptr (Ptr Float)) -> IO [Ptr Float]) -> IO [Ptr Float]
forall a b. CStorable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr (Ptr (Ptr Float)) -> IO [Ptr Float]) -> IO [Ptr Float])
-> (Ptr (Ptr (Ptr Float)) -> IO [Ptr Float]) -> IO [Ptr Float]
forall a b. (a -> b) -> a -> b
$ \Ptr (Ptr (Ptr Float))
cptrspp -> do
        CInt
count <- InstrumentP -> Ptr (Ptr (Ptr Float)) -> IO CInt
c_faust_control_ptrs InstrumentP
ptr Ptr (Ptr (Ptr Float))
cptrspp
        Ptr (Ptr Float)
cptrsp <- Ptr (Ptr (Ptr Float)) -> IO (Ptr (Ptr Float))
forall a. CStorable a => Ptr a -> IO a
peek Ptr (Ptr (Ptr Float))
cptrspp
        [Ptr Float]
cptrs <- Int -> Ptr (Ptr Float) -> IO [Ptr Float]
forall a. CStorable a => Int -> Ptr a -> IO [a]
peekArray (CInt -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral CInt
count) Ptr (Ptr Float)
cptrsp
        Ptr (Ptr Float) -> IO ()
forall a. Ptr a -> IO ()
free Ptr (Ptr Float)
cptrsp
        [Ptr Float] -> IO [Ptr Float]
forall (m :: * -> *) a. Monad m => a -> m a
return [Ptr Float]
cptrs
    -- I need an allocated instrument to get valid control pointers.  But since
    -- I already changed their order to put them in a Map, I have to get the
    -- control names again, which is inefficient but easy to do.
    [(([Text], Control), Text)]
uis <- PatchP -> IO [(([Text], Control), Text)]
getUiControls PatchP
patch
    (InstrumentP, [(([Text], Control), Ptr Float)])
-> IO (InstrumentP, [(([Text], Control), Ptr Float)])
forall (m :: * -> *) a. Monad m => a -> m a
return (InstrumentP
ptr, [([Text], Control)]
-> [Ptr Float] -> [(([Text], Control), Ptr Float)]
forall a b. [a] -> [b] -> [(a, b)]
zip (((([Text], Control), Text) -> ([Text], Control))
-> [(([Text], Control), Text)] -> [([Text], Control)]
forall a b. (a -> b) -> [a] -> [b]
map (([Text], Control), Text) -> ([Text], Control)
forall a b. (a, b) -> a
fst [(([Text], Control), Text)]
uis) [Ptr Float]
cptrs)

-- Patch *faust_allocate(const Patch *patch, int srate);
foreign import ccall "faust_allocate"
    c_faust_allocate :: PatchP -> CInt -> IO InstrumentP

-- int faust_control_ptrs(Patch *inst, FAUSTFLOAT ***out_vals)
foreign import ccall "faust_control_ptrs"
    c_faust_control_ptrs :: InstrumentP -> Ptr (Ptr (Ptr Float)) -> IO CInt

-- void faust_destroy(Patch *patch) { delete patch; }
foreign import ccall "faust_destroy" c_faust_destroy :: InstrumentP -> IO ()

-- | Render chunk of time and return samples.
render :: Audio.Frames -> Audio.Frames -> InstrumentP
    -> [(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
-> InstrumentP
-> [(Ptr Float, Block)]
-> [Vector Float]
-> IO [Vector Float]
render Frames
controlSize Frames
controlsPerBlock InstrumentP
inst [(Ptr Float, Block)]
controls [Vector Float]
inputs = do
    Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless ([Vector Float] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Vector Float]
inputs Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== InstrumentP -> Int
instInputs InstrumentP
inst) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$
        Text -> IO ()
forall (m :: * -> *) a. (Stack, MonadIO m) => Text -> m a
errorIO (Text -> IO ()) -> Text -> IO ()
forall a b. (a -> b) -> a -> b
$ Text
"instrument expects " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Int -> Text
forall a. Show a => a -> Text
showt (InstrumentP -> Int
instInputs InstrumentP
inst)
            Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" inputs, but was given " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Int -> Text
forall a. Show a => a -> Text
showt ([Vector Float] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Vector Float]
inputs)
    let inputSizes :: [Frames]
inputSizes = (Vector Float -> Frames) -> [Vector Float] -> [Frames]
forall a b. (a -> b) -> [a] -> [b]
map (Proxy 1 -> Vector Float -> Frames
forall (chan :: Nat).
KnownNat chan =>
Proxy chan -> Vector Float -> Frames
Audio.vectorFrames (forall {t :: Nat}. Proxy t
forall {k} (t :: k). Proxy t
Proxy @1)) [Vector Float]
inputs
    Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless ((Frames -> Bool) -> [Frames] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (Frames -> Frames -> Bool
forall a. Eq a => a -> a -> Bool
==Frames
blockSize) [Frames]
inputSizes) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$
        Text -> IO ()
forall (m :: * -> *) a. (Stack, MonadIO m) => Text -> m a
errorIO (Text -> IO ()) -> Text -> IO ()
forall a b. (a -> b) -> a -> b
$ Text
"all inputs should be block size " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Frames -> Text
forall a. Pretty a => a -> Text
pretty Frames
blockSize
            Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
": " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> [Frames] -> Text
forall a. Pretty a => a -> Text
pretty [Frames]
inputSizes
    let controlSizes :: [Frames]
controlSizes = ((Ptr Float, Block) -> Frames) -> [(Ptr Float, Block)] -> [Frames]
forall a b. (a -> b) -> [a] -> [b]
map (Proxy 1 -> Block -> Frames
forall (chan :: Nat).
KnownNat chan =>
Proxy chan -> Block -> Frames
Audio.blockFrames (forall {t :: Nat}. Proxy t
forall {k} (t :: k). Proxy t
Proxy @1) (Block -> Frames)
-> ((Ptr Float, Block) -> Block) -> (Ptr Float, Block) -> Frames
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Ptr Float, Block) -> Block
forall a b. (a, b) -> b
snd) [(Ptr Float, Block)]
controls
    Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless ((Frames -> Bool) -> [Frames] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (Frames -> Frames -> Bool
forall a. Eq a => a -> a -> Bool
==Frames
controlsPerBlock) [Frames]
controlSizes) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$
        Text -> IO ()
forall (m :: * -> *) a. (Stack, MonadIO m) => Text -> m a
errorIO (Text -> IO ()) -> Text -> IO ()
forall a b. (a -> b) -> a -> b
$ Text
"all controls should have size " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Frames -> Text
forall a. Pretty a => a -> Text
pretty Frames
controlsPerBlock
            Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
": " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> [Frames] -> Text
forall a. Pretty a => a -> Text
pretty [Frames]
controlSizes

    -- Debug.tracepM "controls" controls
    -- Debug.tracepM "inputs" inputs
    -- Debug.tracepM "blockSize" blockSize
    -- Use ForeignPtr to keep the output arrays alive until I can stuff them
    -- into a V.Vector.
    [ForeignPtr Float]
outputFptrs <- (Int -> IO (ForeignPtr Float)) -> [Int] -> IO [ForeignPtr Float]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM Int -> IO (ForeignPtr Float)
forall a. Storable a => Int -> IO (ForeignPtr a)
Foreign.mallocForeignPtrArray
        (Int -> Int -> [Int]
forall a. Int -> a -> [a]
replicate (InstrumentP -> Int
instOutputs InstrumentP
inst) (Frames -> Int
unframe Frames
blockSize))
    -- Holy manual memory management, Batman.
    [ForeignPtr Float] -> ([Ptr Float] -> IO ()) -> IO ()
forall a b. [ForeignPtr a] -> ([Ptr a] -> IO b) -> IO b
FFI.withForeignPtrs [ForeignPtr Float]
outputFptrs (([Ptr Float] -> IO ()) -> IO ())
-> ([Ptr Float] -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \[Ptr Float]
outputPtrs ->
        [Vector Float] -> (Ptr (Ptr Float) -> IO ()) -> IO ()
forall a. [Vector Float] -> (Ptr (Ptr Float) -> IO a) -> IO a
withVectors [Vector Float]
inputs ((Ptr (Ptr Float) -> IO ()) -> IO ())
-> (Ptr (Ptr Float) -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Ptr (Ptr Float)
inputsP ->
        [Ptr Float] -> (Ptr (Ptr Float) -> IO ()) -> IO ()
forall a b. CStorable a => [a] -> (Ptr a -> IO b) -> IO b
withArray [Ptr Float]
outputPtrs ((Ptr (Ptr Float) -> IO ()) -> IO ())
-> (Ptr (Ptr Float) -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Ptr (Ptr Float)
outputsP ->
        [(Ptr Float, Block)]
-> (CInt -> Ptr (Ptr Float) -> Ptr (Ptr Float) -> IO ()) -> IO ()
forall a.
[(Ptr Float, Block)]
-> (CInt -> Ptr (Ptr Float) -> Ptr (Ptr Float) -> IO a) -> IO a
withControls [(Ptr Float, Block)]
controls ((CInt -> Ptr (Ptr Float) -> Ptr (Ptr Float) -> IO ()) -> IO ())
-> (CInt -> Ptr (Ptr Float) -> Ptr (Ptr Float) -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \CInt
controlCount Ptr (Ptr Float)
controlPtrs Ptr (Ptr Float)
controlValsP ->
            InstrumentP
-> CInt
-> CInt
-> CInt
-> Ptr (Ptr Float)
-> Ptr (Ptr Float)
-> Ptr (Ptr Float)
-> Ptr (Ptr Float)
-> IO ()
c_faust_render InstrumentP
inst
                (Frames -> CInt
c_frames Frames
controlSize) (Frames -> CInt
c_frames Frames
controlsPerBlock)
                CInt
controlCount Ptr (Ptr Float)
controlPtrs Ptr (Ptr Float)
controlValsP
                Ptr (Ptr Float)
inputsP Ptr (Ptr Float)
outputsP
    [Vector Float] -> IO [Vector Float]
forall (m :: * -> *) a. Monad m => a -> m a
return ([Vector Float] -> IO [Vector Float])
-> [Vector Float] -> IO [Vector Float]
forall a b. (a -> b) -> a -> b
$ (ForeignPtr Float -> Vector Float)
-> [ForeignPtr Float] -> [Vector Float]
forall a b. (a -> b) -> [a] -> [b]
map (\ForeignPtr Float
fptr -> ForeignPtr Float -> Int -> Vector Float
forall a. Storable a => ForeignPtr a -> Int -> Vector a
V.unsafeFromForeignPtr0 ForeignPtr Float
fptr (Frames -> Int
unframe Frames
blockSize))
        [ForeignPtr Float]
outputFptrs
    where
    blockSize :: Frames
blockSize = Frames
controlSize Frames -> Frames -> Frames
forall a. Num a => a -> a -> a
* Frames
controlsPerBlock
    c_frames :: Frames -> CInt
c_frames = Int -> CInt
FFI.c_int (Int -> CInt) -> (Frames -> Int) -> Frames -> CInt
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Frames -> Int
unframe
    unframe :: Frames -> Int
unframe (Audio.Frames Int
f) = Int
f

withControls :: [(Ptr Float, Audio.Block)]
    -> (CInt -> Ptr (Ptr Float) -> Ptr (Ptr Float) -> IO a) -> IO a
withControls :: forall a.
[(Ptr Float, Block)]
-> (CInt -> Ptr (Ptr Float) -> Ptr (Ptr Float) -> IO a) -> IO a
withControls [(Ptr Float, Block)]
controls CInt -> Ptr (Ptr Float) -> Ptr (Ptr Float) -> IO a
action = do
    -- Avoid allocating an array if it's constant.
    [IO ()] -> IO ()
forall (t :: * -> *) (m :: * -> *) a.
(Foldable t, Monad m) =>
t (m a) -> m ()
sequence_ [Ptr Float -> Float -> IO ()
forall a. Storable a => Ptr a -> a -> IO ()
Foreign.poke Ptr Float
ptr Float
val | (Ptr Float
ptr, Audio.Constant Int
_ Float
val) <- [(Ptr Float, Block)]
controls]
    [Ptr Float] -> (Ptr (Ptr Float) -> IO a) -> IO a
forall a b. CStorable a => [a] -> (Ptr a -> IO b) -> IO b
withArray [Ptr Float]
ptrs ((Ptr (Ptr Float) -> IO a) -> IO a)
-> (Ptr (Ptr Float) -> IO a) -> IO a
forall a b. (a -> b) -> a -> b
$ \Ptr (Ptr Float)
controlPtrs ->
        [Vector Float] -> (Ptr (Ptr Float) -> IO a) -> IO a
forall a. [Vector Float] -> (Ptr (Ptr Float) -> IO a) -> IO a
withVectors [Vector Float]
vecs ((Ptr (Ptr Float) -> IO a) -> IO a)
-> (Ptr (Ptr Float) -> IO a) -> IO a
forall a b. (a -> b) -> a -> b
$ \Ptr (Ptr Float)
controlValsP ->
        CInt -> Ptr (Ptr Float) -> Ptr (Ptr Float) -> IO a
action (Int -> CInt
FFI.c_int ([Ptr Float] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Ptr Float]
ptrs)) Ptr (Ptr Float)
controlPtrs Ptr (Ptr Float)
controlValsP
    where ([Ptr Float]
ptrs, [Vector Float]
vecs) = [(Ptr Float, Vector Float)] -> ([Ptr Float], [Vector Float])
forall a b. [(a, b)] -> ([a], [b])
unzip [(Ptr Float
ptr, Vector Float
vec) | (Ptr Float
ptr, Audio.Block Vector Float
vec) <- [(Ptr Float, Block)]
controls]

-- void faust_render(
--     Patch *patch,
--     int control_size, int controls_per_block,
--     int control_count, float **control_ptrs, const float **controls,
--     const float **inputs, float **outputs);
foreign import ccall "faust_render"
    c_faust_render :: InstrumentP
        -- control_size -> controls_per_block
        -> CInt -> CInt
        -- control_count -> control_ptrs -> controls
        -> CInt -> Ptr (Ptr Float) -> Ptr (Ptr Float)
        -- inputs -> outputs
        -> Ptr (Ptr Float) -> Ptr (Ptr Float)
        -> IO ()

-- ** state

getState :: InstrumentP -> IO ByteString.ByteString
getState :: InstrumentP -> IO ByteString
getState InstrumentP
inst = (Ptr (Ptr CChar) -> IO ByteString) -> IO ByteString
forall a b. CStorable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr (Ptr CChar) -> IO ByteString) -> IO ByteString)
-> (Ptr (Ptr CChar) -> IO ByteString) -> IO ByteString
forall a b. (a -> b) -> a -> b
$ \Ptr (Ptr CChar)
statepp -> do
    InstrumentP -> Ptr (Ptr CChar) -> IO ()
c_faust_get_state InstrumentP
inst Ptr (Ptr CChar)
statepp
    Ptr CChar
statep <- Ptr (Ptr CChar) -> IO (Ptr CChar)
forall a. CStorable a => Ptr a -> IO a
peek Ptr (Ptr CChar)
statepp
    CStringLen -> IO ByteString
ByteString.packCStringLen
        (Ptr CChar
statep, CSize -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (CSize -> Int) -> CSize -> Int
forall a b. (a -> b) -> a -> b
$ InstrumentP -> CSize
c_faust_get_state_size InstrumentP
inst)

-- | 'getState', but without copying, if you promise to finish with the State
-- before you call 'render', which will change it.
unsafeGetState :: InstrumentP -> IO ByteString.ByteString
unsafeGetState :: InstrumentP -> IO ByteString
unsafeGetState InstrumentP
inst = (Ptr (Ptr CChar) -> IO ByteString) -> IO ByteString
forall a b. CStorable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr (Ptr CChar) -> IO ByteString) -> IO ByteString)
-> (Ptr (Ptr CChar) -> IO ByteString) -> IO ByteString
forall a b. (a -> b) -> a -> b
$ \Ptr (Ptr CChar)
statepp -> do
    InstrumentP -> Ptr (Ptr CChar) -> IO ()
c_faust_get_state InstrumentP
inst Ptr (Ptr CChar)
statepp
    Ptr CChar
statep <- Ptr (Ptr CChar) -> IO (Ptr CChar)
forall a. CStorable a => Ptr a -> IO a
peek Ptr (Ptr CChar)
statepp
    CStringLen -> IO ByteString
ByteString.Unsafe.unsafePackCStringLen
        (Ptr CChar
statep, CSize -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (CSize -> Int) -> CSize -> Int
forall a b. (a -> b) -> a -> b
$ InstrumentP -> CSize
c_faust_get_state_size InstrumentP
inst)

putState :: ByteString.ByteString -> Text -> InstrumentP -> IO ()
putState :: ByteString -> Text -> InstrumentP -> IO ()
putState ByteString
state Text
name InstrumentP
inst =
    ByteString -> (CStringLen -> IO ()) -> IO ()
forall a. ByteString -> (CStringLen -> IO a) -> IO a
ByteString.Unsafe.unsafeUseAsCStringLen ByteString
state ((CStringLen -> IO ()) -> IO ()) -> (CStringLen -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \(Ptr CChar
statep, Int
size) -> do
        let psize :: CSize
psize = InstrumentP -> CSize
c_faust_get_state_size InstrumentP
inst
        Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (Int -> CSize
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
size CSize -> CSize -> Bool
forall a. Eq a => a -> a -> Bool
== CSize
psize) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$
            Text -> IO ()
forall (m :: * -> *) a. (Stack, MonadIO m) => Text -> m a
errorIO (Text -> IO ()) -> Text -> IO ()
forall a b. (a -> b) -> a -> b
$ Text
"inst " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
forall a. Show a => a -> Text
showt Text
name Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" expects state size "
                Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> CSize -> Text
forall a. Show a => a -> Text
showt CSize
psize Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" but got " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Int -> Text
forall a. Show a => a -> Text
showt Int
size
        InstrumentP -> Ptr CChar -> IO ()
c_faust_put_state InstrumentP
inst Ptr CChar
statep

-- size_t faust_get_state_size(const Patch *patch) { return patch->size; }
foreign import ccall "faust_get_state_size"
    c_faust_get_state_size :: InstrumentP -> CSize

-- size_t faust_get_state(const Patch *patch, const char **state);
foreign import ccall "faust_get_state"
    c_faust_get_state :: InstrumentP -> Ptr CString -> IO ()

-- void faust_put_state(Patch *patch, const char *state);
foreign import ccall "faust_put_state"
    c_faust_put_state :: InstrumentP -> CString -> IO ()

-- * util

peekTexts :: Int -> Ptr CString -> IO [Text]
peekTexts :: Int -> Ptr (Ptr CChar) -> IO [Text]
peekTexts Int
count Ptr (Ptr CChar)
textp = do
    [Ptr CChar]
texts <- Int -> Ptr (Ptr CChar) -> IO [Ptr CChar]
forall a. CStorable a => Int -> Ptr a -> IO [a]
peekArray Int
count Ptr (Ptr CChar)
textp
    (Ptr CChar -> IO Text) -> [Ptr CChar] -> IO [Text]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM Ptr CChar -> IO Text
FFI.peekCString [Ptr CChar]
texts

peekTexts0 :: Ptr CString -> IO [Text]
peekTexts0 :: Ptr (Ptr CChar) -> IO [Text]
peekTexts0 Ptr (Ptr CChar)
textp = do
    [Ptr CChar]
texts <- Ptr CChar -> Ptr (Ptr CChar) -> IO [Ptr CChar]
forall a. (Storable a, Eq a) => a -> Ptr a -> IO [a]
Foreign.peekArray0 Ptr CChar
forall a. Ptr a
nullPtr Ptr (Ptr CChar)
textp
    (Ptr CChar -> IO Text) -> [Ptr CChar] -> IO [Text]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM Ptr CChar -> IO Text
FFI.peekCString [Ptr CChar]
texts

-- | Allocate a list of vectors as **float.  Pass nullptr for [], to avoid
-- allocation.
withVectors :: [V.Vector Float] -> (Ptr (Ptr Float) -> IO a) -> IO a
withVectors :: forall a. [Vector Float] -> (Ptr (Ptr Float) -> IO a) -> IO a
withVectors [] Ptr (Ptr Float) -> IO a
f = Ptr (Ptr Float) -> IO a
f Ptr (Ptr Float)
forall a. Ptr a
nullPtr
withVectors [Vector Float]
vs Ptr (Ptr Float) -> IO a
f = [Vector Float] -> ([Ptr Float] -> IO a) -> IO a
forall a. [Vector Float] -> ([Ptr Float] -> IO a) -> IO a
withPtrs [Vector Float]
vs (([Ptr Float] -> IO a) -> IO a) -> ([Ptr Float] -> IO a) -> IO a
forall a b. (a -> b) -> a -> b
$ \[Ptr Float]
ps -> [Ptr Float] -> (Ptr (Ptr Float) -> IO a) -> IO a
forall a b. CStorable a => [a] -> (Ptr a -> IO b) -> IO b
withArray [Ptr Float]
ps Ptr (Ptr Float) -> IO a
f

-- | Convert a list of vectors to a list of pointers, with no copying.
withPtrs :: [V.Vector Float] -> ([Ptr Float] -> IO a) -> IO a
withPtrs :: forall a. [Vector Float] -> ([Ptr Float] -> IO a) -> IO a
withPtrs = (Vector Float -> (Ptr Float -> IO a) -> IO a)
-> [Vector Float] -> ([Ptr Float] -> IO a) -> IO a
forall a b res.
(a -> (b -> res) -> res) -> [a] -> ([b] -> res) -> res
Foreign.withMany Vector Float -> (Ptr Float -> IO a) -> IO a
forall a b. Storable a => Vector a -> (Ptr a -> IO b) -> IO b
V.unsafeWith