/*  
    Linux Dynamic Objects header
    
    This header should be included by filters and by host applications
    using them, in order to be able to use and implement video filters.
 */

/**
   @file livido.h

   @brief Linux Video Dynamic Objects header file
*/

/**
   @mainpage LiViDO :: Linux Video Dynamic Objects


   @section intro Introduction

During the last couple of years we have been observing a blooming
development in the field of realtime video software for the Linux/GNU
platform. An increasing number of artists and other users are
exploring the possibilities of several unique software packages for
video editing, mixing and effect processing.  The question arises here
how we (the developers) balance the growing number of features against
complexity, (re)usability and manageability of larger scale software
design.

As users, we choose our applications because their features fit our
purposes , as developers we serve the needs of the users who want an
increasing number of features added to our applications while we
should focus on flexible core engines and program frameworks.

An elegant solution to this problem is to provide the Free Software
community with  a flexible architecture that allows a shared pool of video
plugins. This brings a number of benefits:

- we can give designers of plugins the opportunity to develop their
(video) processing algorithms without the distraction of resolving
interface problems;
- we can share a set of unique plugins among a great number of programs;
- we can give the user the opportunity to control at least some aspects of
the features they want.

LiViDO design is based upon extensive research that has already gone
into applications such as PD/PDP , FreeJ, EffecTV , Veejay and other video
software applications.

The LiViDO architects will provide a lightweight, flexible API based
upon these established technologies. Currently, they are in the
process of creating a plug-in architecture useful for video editing
-mixing, and modular effect processing.

The API will deliberately be kept short and simple; to achieve
compatibility with a wide range of promising Linux video software
packages it is required to find the greatest common divisor in their logical
behaviour.

The API attempts to give programmers the ability to write simple plugin
video processors in C/C++ and link them dynamically with a range of
software packages (called hosts). It should be possible for any host and
any plugin to communicate through this interface.

Plugins will reside in shared object files (*.so in Linux), suitable
for dynamic linking by dlopen() and family. The file will provide a
number of plugin types that can be used to instantiate actual plugins
so they can be connected to perform these tasks.

Links to user groups and software supporting the LiViDO specification:

- http://www.piksel.no
- http://freej.dyne.org
- http://zwizwa.fartit.com/pd/pdp/overview.html
- http://veejay.sourceforge.net
- http://lives.sourceforge.net
- http://cvs.cinelerra.org/



   @section License
   
   LiViDO source code is free software; you can redistribute it and/or
   modify it under the terms of the GNU Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.
   
   LiViDO source code is distributed in the hope that it will be
   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
   Please refer to the GNU Public License for more details.
   
   You should have received a copy of the GNU Public License along
   with this source code; if not, write to: Free Software Foundation,
   Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

   LiViDO is developed by:

   Denis "jaromil" Rojo - http://rastasoft.org

   Niels Elburg - http://veejay.sf.net

   Gabriel "Salsaman" Finch - http://lives.sourceforge.net

   Tom Schouten - http://zwizwa.fartit.com

   Andraz Tori - http://cvs.cinelerra.org

*/

#ifndef __LIVIDO_H__
#define __LIVIDO_H__

/** inttypes.h gives bit precision on integer types used
    (u)int(8,16,32,64)_t = (un)signed integer of a certain bit
    depth */
#include <inttypes.h>

/** buffer allocation routines from libc */
#include <stdlib.h>

/////////////////////////////////////////////////////////////////
/// LIVIDO API VERSION 1
/////////////////////////////////////////////////////////////////

/*

  $Log: livido.h,v $
  Revision 1.3  2004/07/07 12:04:22  salsaman

  Updated documantation, fixed create instance

  Revision 1.2  2004/06/30 17:36:09  jaromil


  commit from trans.hackmeeting in MPhacklab:
  multiple input and output video channels,
  timecodes on frames,
  more palettes and mask-type palettes,
  more parameter types,
  general cleanup and review with Salsaman.

  Revision 1.1.1.1  2004/05/02 14:28:32  jaromil

  fresh import of LiViDO header core and examples,
  second review on sunday 2 may 2004


  Revision 1.6  salsaman
  Add support for channels


  Revision 1.5  2004/04/06 08:39:41  jaromil


  removed alloca() function,
  define to create instances from class,
  public parameters allocation and set.
  this update discards compatibility with previous revision.

  Revision 1.4  2004/03/30 18:57:20  jaromil


  now API includes class / instance mechanism
  see documentation in doxygen format inside livido.h

  also new working examples: plugin and host
  only libc needed: simple but works.

  comments welcome!


  Process me with doxygen to generate html documentation,
  or read thru this file, to explore the LiViDO API.

*/

#define LIVIDO_ID "$Id: livido.h,v 1.3 2004/07/07 12:04:22 salsaman Exp $"
///< last modification






/** 
    @defgroup palette Video palettes
    
    Livido Video Palettes
    
    a filter can specify more than one supported palette
    
    @{ */
typedef int livido_palette_t;
#define LVD_PALETTE_RGB24	1 ///< please comment me
#define LVD_PALETTE_RGB32	2 ///< please comment me
#define LVD_PALETTE_RGBP	3 ///< please comment me
#define LVD_PALETTE_RAW		4 ///< please comment me
#define	LVD_PALETTE_YUV422P	5 ///< please comment me
#define LVD_PALETTE_YUV420P	6 ///< please comment me
#define LVD_PALETTE_YUV444P	7 ///< please comment me
#define LVD_PALETTE_YUY2	8 ///< YUV422
#define	LVD_PALETTE_YUYV	9 ///< please comment me
#define	LVD_PALETTE_YV12	10 ///< YUV420
#define	LVD_PALETTE_I420	11 ///< YUV420
#define LVD_PALETTE_UYVY        12 ///< YUV422 packed
#define LVD_PALETTE_ALPHA8      13 ///< alpha channel 8 bit
#define LVD_PALETTE_ALPHA16     14 ///< alpha channel 16 bit
#define LVD_PALETTE_BGR24       15 ///< RGB LE
#define LVD_PALETTE_BGR32       16 ///< RGBA LE

/** Palettes greater than 1024 are masks */

#define LVD_PALETTE_BITMAP1 1024
#define LVD_PALETTE_BITMAP2 1025
#define LVD_PALETTE_BITMAP4 1026
#define LVD_PALETTE_BITMAP8 1027

#define LVD_PALETTE_END         (0x0)    ///< marker for end of palette list

/**
   a define to know how many bytes per pixel is each palette 
   @todo please correct any errors as i'm not 100% about bpp in palettes
*/

#define LIVIDO_PALETTE_BYTES(p) \
        (p==LVD_PALETTE_RGB32)| \
        (p==LVD_PALETTE_GBR32)?4: \
        (p==LVD_PALETTE_YUV422P)| \
        (p==LVD_PALETTE_420P)| \
        (p==LVD_PALETTE_RGB24)| \
        (p==LVD_PALETTE_GBR24)| \
        (p==LVD_PALETTE_YUV444P)| \
        (p==LVD_PALETTE_YUYV)| \
        (p==LVD_PALETTE_UYVY)| \
        (p==LVD_PALETTE_YUY)| \
        (p==LVD_PALETTE_YV12)| \
        (p==LVD_PALETTE_I420)?3: \
        (p==LVD_PALETTE_ALPHA16)?2: \
        (p==LVD_PALETTE_RGBP)| \
        (p==LVD_PALETTE_RAW)| \
        (p==LVD_PALETTE_ALPHA8)?1: \
        (p==LVD_PALETTE_BITMAP1)?.125: \
        (p==LVD_PALETTE_BITMAP2)?.250: \
        (p==LVD_PALETTE_BITMAP4)?.500: \
        (p==LVD_PALETTE_BITMAP8)?1:0
///< check how many bytes is a palette

#define LIVIDO_PALETTE_BITS(p) \
        (p==LVD_PALETTE_RGB32)| \
        (p==LVD_PALETTE_GBR32)?32: \
        (p==LVD_PALETTE_YUV422P)| \
        (p==LVD_PALETTE_420P)| \
        (p==LVD_PALETTE_RGB24)| \
        (p==LVD_PALETTE_GBR24)| \
        (p==LVD_PALETTE_YUV444P)| \
        (p==LVD_PALETTE_YUYV)| \
        (p==LVD_PALETTE_UYVY)| \
        (p==LVD_PALETTE_YUY)| \
        (p==LVD_PALETTE_YV12)| \
        (p==LVD_PALETTE_I420)?24: \
        (p==LVD_PALETTE_ALPHA16)?16: \
        (p==LVD_PALETTE_RGBP)| \
        (p==LVD_PALETTE_RAW)| \
        (p==LVD_PALETTE_ALPHA8)?8:0
///< check how many bits is a palette

/// @}





/////////////////////////////////////////////////////////////////
/**
   @defgroup Video channels
   
   Channels templatesare created by the plugin and offered to the host as part
   of the Plugin Class received when the setup function is called on
   the plugin.

   These fields container pointers to the first input and output
   channels respectively, which are the initial elements of arrays terminated by
   a channel with palettes[0]==LVD_PALETTE_END.

   When the host receives the *in_channel and *out_channel arrays from
   the plugin, it must process them to see what channels are available,
   and decide which it will use.

   The host should copy the channel templates to real channels, for each channel in turn, 
   the host should decide which of the palettes in the list it would like to use, remembering 
   that the list is in order of preference for the plugin. If none of the
   palettes are suitable in a channel, the host cannot use that
   channel.

   Assuming one of the palettes in the list is acceptible to the host,
   the host indicates this by setting the value of palettes[0] to the
   chosen palette.

   If a channel is optional, the host can indicate it will use it by resetting the 
   optional flag to 0 in its copy of the channels.

   The final task for the host is to set the channel width and
   height. This is only important if the plugin has not set the
   property LIVIDO_PROPERTY_CAN_RESIZE, otherwise the channel takes
   the size of the frame (see below).

   If the "same_palette" field is set for any of the channels, the host
   should check that palettes[0] matches with the other channel.

   If the "same_size" field is set for any of the channels, the host
   should check that width and heigth match with the other channel.


   @{ */
/////////////////////////////////////////////////////////////////

/**
   This structure is a template describing every single channel, it is
   held by the class and defined when the plugin instance is created.
*/
typedef struct {

  /** This field can be set to the name of the channel (e.g. "Input
      channel 1" if the plugin author likes, otherwise it should be
      set to NULL. This is a descriptive field. */
  char name[512]; ///< name of channel or NULL

  /** If this field is set to a positive value, then the host can skip
      using this channel by leaving the value positive, otherwise it should be 
      reset to zero if the host wishes to use it */

  int optional; ///< channel is optional or mandatory

  /** The plugin should set this to an array of palettes it can accept
      on this channel, in order of preference, terminated by a
      LVD_PALETTE_END (#defined as 0x0).
      When initialized inside the instance, the first place of this
      array (palettes[0]) holds the palette selected by the host.
  */
  livido_palette_t *palettes;
  
  /** The plugin can use this field to tell the host that the settings
      of palette choice must match that of another channel. A normal
      use would be to mark the first output channel must match the
      first input channel. A positive value means "must match input
      channel n", a negative value means "must match output channel
      n". A setting of zero implies a free choice for palette and size
      settings. The host should not change any of the "same_" values,
      otherwise the plugin may behave unpredictably. */
  int same_palette; ///< palette must be set to same as other channel

  int width; ///< channel width in pixels

  int height; ///< channel height in pixels

  /** The plugin can use this field to tell the host that the settings
      of channel size must match that of another channel. A normal use
      would be to mark the first output channel must match the first
      input channel. A positive value means "must match input channel
      n", a negative value means "must match output channel n". A
      setting of zero implies a free choice for palette and size
      settings. The host should not change any of the "same_" values,
      otherwise the plugin may behave unpredictably. */
  int same_size; ///< size must be set to same as other channel

  int rowstrides[4]; ///< lenght of one row in bytes, for each color channel

  void *extra; ///< extra data for the channel, reserved for future use 

} livido_channel_t;

/// @}





/////////////////////////////////////////////////////////////////
/**
   @defgroup Frame Format

   Frames in LiViDO are passed as structures. They hold the actual
   pixel data along with geometrical informations about it.
   
   They are used by the initialization function of filter Instances
   (see filter_public module) to describe the frame size of processed
   video. In case the filter has no LIVIDO_PROPERTY_RESIZABLE the
   sizes may not change during processing.
   
   Frames are also used for masks, which have a pixel data of 1 byte
   per pixel. In case masks are present for input or output of plugins,
   they are interleaved to the frames.

   
   @{ */
/////////////////////////////////////////////////////////////////

/**
   This structure stores the frame data along with informations on its
   geometry. It is used to pass frames to the process.
*/

typedef struct {
  uint64_t time_usec;         // microseconds since 'play start'
  int64_t frame_number; // frame number or 0 if undefined
} livido_timecode_t;


#define LIVIDO_TIMECODE_END \
{0, 0}


typedef struct {

  livido_timecode_t timecode;

  float x; ///< x position of the frame, 0 by default

  float y; ///< y position of the frame, 0 by default

  void *pixel_data; ///< pointer to the actual pixel data

  void *audio_data; ///< pointer to the audio data along the video
 
  void *extra; ///< extra pointer for future reference, unions

} livido_frame_t;

#define LIVIDO_FRAME_END \
{ LIVIDO_TIMECODE_END,0.,0.,NULL,NULL,NULL }
///< small define to mark the end of frames when the array is declared

/// @}






/////////////////////////////////////////////////////////////////
/**
   @defgroup instance Filter instance
   
    
   An instance is the buffer created by the filter at initialization
   
   @todo write something more here about the instance mechanism, that
   is what basically lets us use the same plugin multiple times...
   
   @{ */
/////////////////////////////////////////////////////////////////

/**
   This struct is allocated by the plugin init()
   
   it should be stored by the host and free'd at the end using
   the plugin function deinit()
   
   All variables inside the livido_instance are read and write, so they
   should be set by the host application before calling the alloca()
   function.

   The parameters array holds the real values for the parameters exposed
   by the filter, some of them require a new call to init() in case
   the livido_parameter_t::need_init flag is positive.  */
typedef struct {
  /** this is where the actual parameter values are stored, it must be
      allocated by the filter when the instance is created

      @todo macros to get/set parameters casted in proper types
  */
  void **parameter; ///< filter parameter values

  livido_channel_t *in_channels; ///< arrays terminated by a channel with 
                                 ///palettes[0]==LVD_PALETTE_END

  livido_channel_t *out_channels; ///< arrays terminated by a channel with 
                                 ///palettes[0]==LVD_PALETTE_END

  void *internal; ///< filter's private buffers

  char *error; ///< if there is an error is holding its description, NULL otherwise

} livido_instance_t;


/// @}




///////////////////////////////////////////////////////////////////
/** 
    @defgroup filter_public Filter class public functions
    
    The following public functions are found in the filter class,
    they are called by the host application to operate the filter.

    First the livido_setup symbol is called, which returns a
    structure which is the filter's class. The class will hold
    function pointers for the init() deinit() alloca() and process()
    functions.

    An host application should first setup the width, height and
    palette of the class, then it can proceed to create a new instance.
    
    The init() must be called in order to create an instance of
    the filter, which will be in turn passed to process() every
    time video input are processed into output.

    @{ */
///////////////////////////////////////////////////////////////////

/**
    Initialize the internal buffers and variables for a 
    instance of the filter, according to the parameters set.

    This function should be used on a freshly created filter instance,
    as well every time a parameter which needs init
    (see livido_parameter_t::need_init) is changed.

    It means that the init function must be REENTRANT.

    @brief initialize filter instance according to its parameters
    @param livido_instance_t filter instance to (re)initialize
    @param livido_frame_t descriptive frame instance to pass over geometrical informations
           this is important for filter that don't have LIVIDO_PROPERTY_RESIZABLE set.
    @return initialized filter instance
    */
typedef livido_instance_t *(livido_init_f) (livido_instance_t*);

/**
   Free memory and cleanup internal variables.
   
   It must be called by host for de-initialization of instances when they
   are no more needed.
   
   @param filter instance
   @return error code
*/
typedef int (livido_deinit_f) (livido_instance_t*); 

/**
   Process instance->input frames to instance->output frames
   
   if LVD_PROPERTY_INPLACE is set , livido_data **out may be NULL
   
   @param env filter instance
   @param in input frame(s) to be processed, NULL terminated
   @param out output frame(s) processed, NULL terminated
          this is NULL if LIVIDO_PROPERTY_IS_INPLACE
   @return error code */
typedef int (livido_process_f) (livido_instance_t* instance,
				livido_frame_t **in, livido_frame_t **out);

///@}
















/** 
    @defgroup property Filter properties
    
    Properties of a filter define aspects of its functioning,
    they are flags set on the filter class, you can check them
    from the varialbe 'property' contained in it, i.e:
    if(property&LIVIDO_PROPERTY_*)

    Filters can have the following properties:

    @{ */


/**
   If this property is set, means that the filter can run in a (soft)
   realtime environment. The plugin must not do:
					 
   -# use malloc() free() or other memory managment functions that
   allocate/free data during processing.
   -# the plugin does not access (special) files in blocking
   operations
   -# the plugin does not do any colour space conversions but has
   internal routines for processing various colour spaces
   -# host is responsible for timing operations
*/
#define LIVIDO_PROPERTY_REALTIME (1<<0x0) 
///< realtime filter property

/**
   If this property is set, the filter can do inplace operations then
   the plugin process() function will return NULL in *output and all
   the result will be in input (saves a memcpy on certain filters)
*/
#define LIVIDO_PROPERTY_INPLACE (1<<0x1)
///< inplace filter property

/**
   If this property is set, the filter is a transition between two
   video sources, like wipes that are applied for a certain lapse
   of time usually taking 2 input and producing 1 output
*/
#define LIVIDO_PROPERTY_TRANSITION (1<<0x2)
///< transition filter property

/**
   If this property is set, the filter needs to receive 8bit masks
   interleaved into the input and/or output frames array sent to the
   process function.
   
   Masks are byte planes holding positional information to be mapped
   on top of frames by plugins; for instance there can be a luminance
   mask or any other overlay function masks.
*/
#define LIVIDO_PROPERTY_MASKED (1<<0x3)
///< filter need planar masks interleaved to frames

/**
   If this property is set, the filter can smoothly handle different
   frame sizes for each input and output frames.

   If this property is not present, then all the input and output frames
   fed into the process, as well the masks if present, must match the
   same width and height physical size.
*/
#define LIVIDO_PROPERTY_RESIZABLE (1<<0x4)

///@}







/////////////////////////////////////////////////////////////////
/**
   @defgroup parameter Filter parameters
   
   Livido Parameters are used by the plugin to describe the the
   controls of its filter, they should be parsed by the host loading
   the plugin to understand which values should be changed by the
   (user) interface.
    
   *PLEASE NOTE* That the real values are not stored here, but in the
   filter instance.
   
   @{ */
/////////////////////////////////////////////////////////////////


enum livido_param_type_enum {
  LVD_PARAM_BOOL, ///< on/off switch
  LVD_PARAM_NUMBER, ///< number value
  LVD_PARAM_RGB24, ///< color triplet for red green and blue
  LVD_PARAM_RGBA32, ///< color triplet for red green blue and alpha 
  LVD_PARAM_COORD2D, ///< 2d cartesian coordinates
  LVD_PARAM_STRING, ///< text string
  LVD_PARAM_TRANSITION, ///< amount of transition, from 0. (no transition) to 1. (full trans)
  LVD_PARAM_DATA, ///< pointer to custom data buffer
  LVD_PARAM_END ///< end of parameter declaration
};



/**
   It holds some variables that are interesting for the
   user interface, to render triggable realtime by users.

   @brief Struct to describe the public parameters of the plugin
*/
typedef struct {
const	char 	*name;	      ///< name
const	char	*description; ///< description
const   char    *hint;        ///< layout hints for the interface renderer

                              /// hints should use the keyword system, e.g:
                              /// layout|p1|fill|p2
                              /// special|aspect|1|2

const	int	type;	      ///< the parameter type (see livido_param_type_enum)
const   int     group;        ///< group parameters on positive values, zero means no group
const	float 	min;	      ///< minimum value
const	float	max;	      ///< maximum value
const   void	*def;         ///< default value
const   int     decimals;     ///< decimal places after the floating point
/** Some parameters require internal buffers to be recalculated when
    their value changes, this flag specifies that: when need_init is
    holding a positive value, the host application should call the
    livido_class_t::init function after setting a new value on this
    parameter. */
const   int	needs_init; ///< requires the host to call the init function when changed
} livido_parameter_t;


#define LIVIDO_PARAM_END \
{ NULL, NULL, NULL, LVD_PARAM_END, 0, 0., 0., NULL, 0, 0 }
///< small define to mark the end of parameters when the array is declared

///@}




/**
   @defgroup class Filter class

   The class is the filter abstraction returned by the livido_setup()
   function, which is a symbol always found in every livido plugin.

   The setup function must be called only once, the first time the
   filter is loaded, and returns a structure holding pointers to
   all functions needed to operate a filter.

   Most notably the class will contain the name of the filter,
   its property flags, palettes supported and preferred and the
   init() deinit() and process() functions, while it will also
   hold the width and height geometry for the instance when is
   created by init().

   After calling the livido_setup(), an host application must call
   init() to obtain an instance of the class.
    
   @{ */

typedef struct {

  char *name; ///< name of filter
  char *author; ///< author of filter
  char *description; ///< long text description
  int version; ///< filter version
  
  int livido_api_version; ///< version of the livido api used
  
  int property;
  ///< filter properties
  
  livido_parameter_t		*parameters;
  ///< NULL terminated array of parameter descriptions
  

  /* host should copy these channel arrays, set the palettes and optional flags,
     and then pass them into CREATE_INSTANCE, where they will be copied again for the plugin 
     host should free its own copy of channels */


  livido_channel_t *in_channels;  // in_channels template
                                  ///< arrays terminated by a channel with 
                                  ///palettes[0]==LVD_PALETTE_END

  livido_channel_t *out_channels;  // out_channels template
                                   ///< arrays terminated by a channel with 
                                   ///palettes[0]==LVD_PALETTE_END
 

  /* function pointers follow */
  livido_init_f 			*init;
  ///< init function creates a filter instance
  livido_deinit_f		*deinit; 
  ///< deinit function destroys a filter instance
  livido_process_f 		*process;
  ///< process function munches input videos in output
  
  void *extra; ///< extra data pointer reserved for future use
  
} livido_class_t;
#define LIVIDO_CLASS_END \
{ NULL,NULL,NULL,\
 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, \
   NULL,LIVIDO_CHANNEL_END,LIVIDO_CHANNEL_END,NULL,NULL,NULL,NULL }

/**
   the Setup is called by the host only the first time a plugin file is loaded,
   it doesn't needs to be called at every filter instance being created
   (that is the livido_init)

   It returns a null terminated array of filter classes made available
   by the plugin.

   @brief Setup the global environment of the plugin.
   @return NULL terminated array of filter classes available */
typedef livido_class_t *(livido_setup_f) (void);



/// @}


/**
   This define is a handy way to create new filter instances from a
   filter class, it might be used by the host application once a 
   plugin class is created.
   
   It executes the following operations:

   - allocate the instance buffer
   - allocate the buffers needed for the filter parameters
   - copy in_channels and out_channels supplied by host into the instance
   - set the filter parameters to the default values
   - set the internal filter instance buffer to NULL

   the above operations are necessary to create a breand new filter
   instance before setting it up and passing it to the init()

   @brief create a new clean filter instance from a filter class
   @param cl filter class
   @param inst pointer where to store the new filter instance */
#define LIVIDO_CREATE_INSTANCE(cl,inst,in_channels,out_channels) \
{ int c; size_t b; \
inst = malloc(sizeof(livido_instance_t)); \
if (cl->parameters) { \
 for(c=0;cl->parameters[c].type!=LVD_PARAM_END;c++); \
 inst->parameter = malloc(sizeof(void*) *c); c--; \
 for(; c>0; c--) { switch(cl->parameters[c].type) { \
	case LVD_PARAM_BOOL: b=sizeof(int); break; \
	case LVD_PARAM_NUMBER: b=sizeof(float); break; \
	case LVD_PARAM_RGB24: b=sizeof(unsigned int)*3; break; \
	case LVD_PARAM_RGBA32: b=sizeof(unsigned int)*4; break; \
	case LVD_PARAM_COORD2D: b=sizeof(int)*2; break; \
	case LVD_PARAM_STRING: b=sizeof(char)*256; break; \
        case LVD_PARAM_TRANSITION: b=sizeof(float); break;
	case LVD_PARAM_DATA: b=sizeof(void*); break; \
        default: b=sizeof(void*); \
	} \
  inst->parameter[c] = malloc(b); \
  memcpy(inst->parameter[c] , cl->parameters[c].def , b); \
  } \
 } \
for(c=0;in_channels[c].palettes[0]!=LVD_PALETTE_END; c++);  \
in_array=malloc(++c*sizeof(livido_channel_t)); \
for(--c;c>=0;c--) \
  memcpy(&in_array[c],&in_channels[c],sizeof(livido_channel_t)); \
for(c=0;out_channels[c].palettes[0]!=LVD_PALETTE_END; c++);  \
out_array=malloc(++c*sizeof(livido_channel_t)); \
for(--c;c>=0;c--) \
  memcpy(&out_array[c],out_channels[c],sizeof(livido_channel_t)); \
inst->in_channels=in_array; \
inst->out_channels=out_array; \
inst->internal = NULL; }

#define LIVIDO_FREE_INSTANCE(cl,inst) \
{ int c; \
if (cl->parameters) { \
 for(c=0;cl->parameters[c].type!=LVD_PARAM_END;c++) \
	free( inst->parameter[c] ); \
 } \
free (inst->in_channels); \
free (inst->out_channels); \
}

#endif // __LIVIDO_H__
