packages feed

gegl-0.0.0.1: src/GEGL/FFI/Node/State.hs

{-# LANGUAGE ForeignFunctionInterface, TemplateHaskell, QuasiQuotes #-}

module GEGL.FFI.Node.State
  ( c_gegl_node_get_consumers
  , c_gegl_node_get_producer
  , c_gegl_node_get_bounding_box
  ) where

import GEGL.FFI.Node
import GEGL.FFI.Tuple
import GEGL.FFI.Rectangle

import Data.Monoid ((<>))

import Language.C.Types
import Language.C.Inline as C

import Foreign.Marshal.Array
import Foreign.Marshal.Alloc (free)
import Foreign.C.String
import Foreign.Ptr
import Foreign.Storable (peek)

C.context (C.baseCtx <> tupleCtx)

C.include "<gegl.h>"
C.include "../Tuple.h"

-- | Interface to the @gegl_node_get_consumers@ function in C.
c_gegl_node_get_consumers
  :: Ptr ()                 -- ^ Node to get consumers of
  -> CString                -- ^ Name of output pad
  -> IO [(Ptr (), CString)] -- ^ List of consuming nodes
c_gegl_node_get_consumers node name = do
  tupPtr <- [C.block| nodeWithPad * {
    static nodeWithPad tuple;
    static GeglNode ** nodes;
    const static char ** pads;
    int len = gegl_node_get_consumers(
        $(void * node)
      , $(char * name)
      , &nodes
      , &pads
      );
    tuple.length = len;
    tuple.data = nodes;
    tuple.names = (char **)pads;
    return &tuple;
    }|]
  tup <- peek tupPtr
  let clength = nwpLength tup
      dptr    = nwpData tup
      dlength (CInt c) = fromIntegral c
      length  = dlength clength
  nodes <- peekArray length dptr
  names <- peekArray length $ nwpNames tup
  free dptr
  free $ nwpNames tup
  return $ zip nodes names

-- | Interface to the @egl_node_get_producer@ function in C.
c_gegl_node_get_producer
  :: Ptr ()  -- ^ Node to get Producer of
  -> CString -- ^ Name of the input pad
  -> IO (Maybe (Ptr (), CString))
c_gegl_node_get_producer node name = do
  nwpPtr <- [C.block| producer * {
    static producer nwp;
    static GeglNode * node;
    static char * pad_name;
    node = gegl_node_get_producer(
        $(void * node)
      , $(char * name)
      , &pad_name
      );
    nwp.node = node;
    nwp.pad  = pad_name;
    return &nwp;
    }|]
  nwp <- peek nwpPtr
  if prodNode nwp == nullPtr
  then return Nothing
  else return $ Just $ (prodNode nwp, prodPad nwp)

-- | Interface to the @gegl_node_get_bounding_box@ function in C.
c_gegl_node_get_bounding_box
  :: Ptr ()                 -- ^ A 'GeglNode'
  -> IO (Ptr GeglRectangle) -- ^ The bounding box of the node
c_gegl_node_get_bounding_box node = do
  rectPtr <- [C.block| void * {
    static GeglRectangle a;
    static void * b;
    a = gegl_node_get_bounding_box($(void * node));
    b = (void *)&a;
    return b;
    }|]
  return $ castPtr rectPtr