/*  
    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 Lesser General 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 Lesser General 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
/////////////////////////////////////////////////////////////////

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

#define LIVIDO_ID "$Id$"
///< last modification

#define LIVIDO_HEADER_VERSION 	0

/** 
    @defgroup palette Video palettes
    
    Livido Video Palettes
    
    a filter can specify more than one supported palette

    IMPORTANT: If applications use their own numbers, ask on the list to be assigned
               Do not put your personal definitions inside livido.h!
    GOOD PRACTICE: Palette names should be unambiguous.
                   We will add them when we have real applications using it, 
                   not because of theoretical ideas.
    
    @{ */


typedef int32_t livido_palette_t;
#define LVD_PALETTE_RGB888		1  
#define LVD_PALETTE_RGBA8888		2  
#define LVD_PALETTE_RGB161616		3  
#define LVD_PALETTE_RGBA16161616	4  
#define LVD_PALETTE_YUV888		5  
#define	LVD_PALETTE_YUVA8888		6
#define	LVD_PALETTE_YUV161616		7  
#define	LVD_PALETTE_YUVA16161616	8 
#define	LVD_PALETTE_YUV422P		9 ///< 8 bits per channel!
#define LVD_PALETTE_YUV420P		10 ///< 8 bits per channel!
#define LVD_PALETTE_YUV444P		11 ///< 8 bits per channel!
#define LVD_PALETTE_A8     		12 ///< single value channel (for example alpha) 8 bpp
#define LVD_PALETTE_A16     		13 ///< single value channel (for example alpha) 16 bpp
#define LVD_PALETTE_RGBFLOAT		14
#define LVD_PALETTE_RGBAFLOAT		15
#define LVD_PALETTE_AFLOAT		16
#define LVD_PALETTE_BGR888		17
#define LVD_PALETTE_YUYV8888		18
#define LVD_PALETTE_UYVY8888		19
#define LVD_PALETTE_RGB565		20
#define LVD_PALETTE_RGBX8888		21
#define LVD_PALETTE_A4     		22 ///< single value channel 4 bpp
#define LVD_PALETTE_A2     		23 ///< single value channel 2 bpp
#define LVD_PALETTE_A1     		24 ///< single value channel 1 bpp

#define  LVD_PALETTE_FIRST_CUSTOM 2048


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


/**
   a define to know how many bytes per pixel is each palette 
   this function rounds UP!
*/

///< check how many bits is a palette
#define LIVIDO_PALETTE_BITS(p) ( \
        (p == LVD_PALETTE_RGBAFLOAT)    ? 128 : \
        (p == LVD_PALETTE_RGBFLOAT)     ? 96 : \
        (p == LVD_PALETTE_RGBA16161616) || \
        (p == LVD_PALETTE_YUVA16161616) ? 64: \
        (p == LVD_PALETTE_RGB161616)    || \
        (p == LVD_PALETTE_YUV161616)    ? 48 : \
        (p == LVD_PALETTE_RGBA8888)     || \
        (p == LVD_PALETTE_RGBX8888)     || \
        (p == LVD_PALETTE_YUVA8888)     || \
        (p == LVD_PALETTE_AFLOAT)   	|| \
        (p == LVD_PALETTE_YUV444P)      ? 32 : \
        (p == LVD_PALETTE_RGB888)       || \
        (p == LVD_PALETTE_BGR888)       || \
        (p == LVD_PALETTE_YUV888)       ? 24 : \
        (p == LVD_PALETTE_YUV422P)      || \
        (p == LVD_PALETTE_YUYV8888)     || \
        (p == LVD_PALETTE_UYVY8888)     || \
        (p == LVD_PALETTE_RGB565)       || \
        (p == LVD_PALETTE_A16)      	? 16: \
        (p == LVD_PALETTE_YUV420P)      ? 12: \
        (p == LVD_PALETTE_A8)		? 8: \
        (p == LVD_PALETTE_A4)		? 4: \
        (p == LVD_PALETTE_A2)		? 2: \
        (p == LVD_PALETTE_A1)		? 1: 0)



///< check if the palette is plannar
#define LIVIDO_PALETTE_IS_PLANAR(p) ( \
        (p == LVD_PALETTE_YUV444P)      || \
        (p == LVD_PALETTE_YUV422P)      || \
	(p == LVD_PALETTE_YUV420P)	? 1 :0 )


#define LIVIDO_PALETTE_IS_CUSTOM(p) ( \
        (p&2048) ? 1 : 0 )

///< check how many bytes is a palette
#define LIVIDO_PALETTE_CHANNELS(p) ( \
        (p == LVD_PALETTE_RGBAFLOAT)    || \
        (p == LVD_PALETTE_RGBA16161616) || \
        (p == LVD_PALETTE_RGBA8888)     || \
        (p == LVD_PALETTE_RGBX8888)     || \
        (p == LVD_PALETTE_YUVA8888)     || \
        (p == LVD_PALETTE_YUYV8888)     || \
        (p == LVD_PALETTE_UYVY8888)     || \
        (p == LVD_PALETTE_YUVA16161616) ? 4 : \
        (p == LVD_PALETTE_RGBFLOAT)     || \
        (p == LVD_PALETTE_RGB161616)    || \
        (p == LVD_PALETTE_RGB888)       || \
        (p == LVD_PALETTE_BGR888)       || \
        (p == LVD_PALETTE_YUV888)       || \
        (p == LVD_PALETTE_YUV161616)    || : \
        (p == LVD_PALETTE_RGB565)       || \
        (p == LVD_PALETTE_YUV422P)      || \
        (p == LVD_PALETTE_YUV420P)      || /* 4:2:0 is actually 12 bits per pixel! */ \
        (p == LVD_PALETTE_YUV444P)      ? 3 : \
        (p == LVD_PALETTE_AFLOAT)   	|| \
        (p == LVD_PALETTE_A16)      	|| \
        (p == LVD_PALETTE_A8)		|| \
        (p == LVD_PALETTE_A4) 		|| \
        (p == LVD_PALETTE_A2) 	  	|| \
        (p == LVD_PALETTE_A1)       	? 1 : 0)


/////////////////////////////////////////////////////////////////
/**
   @defgroup livido_channel_template_t Video channel template
   
   Channels templates are created by the plugin and offered to the host as part
   of the instance template received when the livido_setup function is called on
   the plugin.

   These fields contain pointers to the first input and output
   channels respectively, which are the initial elements of arrays terminated by
   a channel with palettes==NULL.

   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 and how.

   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. If channel that cannot be used is not optional, host cannot use this plugin.

   Assuming one of the palettes in the list is acceptible to the host,
   the host indicates this by setting the value of palette in livido_channel_t struct

   If a channel is optional, the host can indicate not using the channel
   by setting disabled to 1 in channels that get passed to init

   The final task for the host is to set the channel width and
   height. If livido_channel_template_t.width is nonzero, the only possible 
   size that channel can take is denoted as width and heigth parameters of the template.
   
   The final task for the host is to set the channel width and height. 
   In case that inside livido_instance_t.flags flag 
   LIVIDO_PROPERTY_STATIC_PALETTES or LIVIDO_PROPERTY_STATIC_SIZES is set, 
   channels' palettes or sizes are not allowed to change at any time after 
   instance initialization. If host sill wants to do the change, host must 
   deinitialize the plugin and initialize it again.

   If the "same_as" field is set for any of the channels, the host
   should check that palette or size matches with the other channel.
   What must match is denoted by the flag LIVID_CHANNEL_SAME_AS_SIZE
   and/or LIVIDO_CHANNEL_SAME_AS_PALETTE inside livido_instance_t.flags
   


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

/**
   This structure is a template describing every single possible channel, it is
   held by the instance template and used to put create livido_channel_t structures passed
   back to plugin at initialization of the instance
   IMPORTANT: Host NEVER changes any part of this structure
*/
typedef struct {

  /** This field can be set to the name of the channel (e.g. "Input
      channel 1" if the plugin author likes. 
      IMPORTANT: Never set the name to point to NULL since that denotes the end of list
      GOOD PRACTICE: Avoid using words like "channel" inside the name, since it is implicit
  */
  char *name; ///< name of channel

  /** The plugin sets 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).
      The host writes selected value in livido_channel_t.palette
  */
  livido_palette_t *palettes;
  
  /** The plugin can use this field to tell the host that the settings
      of palette or sizee 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. 
      
      IMPORTANT: same_as can only reference channels that 
      have serial numbers smaller then current (and in case of output 
      channels they can also reference all input channels, but input
      channels _canno_T reffer to output channels). 
      This way we avoid circular dependencies!
  */
  uint32_t same_as; ///< palette must be set to same as other channel

  /** 
  	Flags that give information on usage and hints
  */
  uint32_t flags; ///< 


  /** Channel width and height. Leave them at 0 for host to chose
      them arbitrary. 
      
      IMPORTANT: You cannot just set height but leave width arbitrary 
      or vice versa. Both have to be zero or both have to be some other 
      value  
  */   
  uint32_t width; 
  uint32_t height;

  /** 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. 
      
      IMPORTANT: both same_palette can only reference channels that 
      have serial numbers smaller then current (and in case of output 
      channels they can also reference all input channels, but input
      channels _canno_T reffer to output channels). 
      This way we avoid circular dependencies!
      GOOD PRACTICE: same_palette and same_size should in most cases
      point to the same channel. It is very complicated for hosts
      to handle all this correctly, so be gentle.
  */
  char reserved[32];
} livido_channel_template_t;


// flags that flag property can have

/** One or more of these flags can assist the host in setting up
    channel arrays */

#define LIVIDO_CHNLTMPL_OPTIONAL (1<<0)
///< tell host that channel can be disabled

#define LIVIDO_CHNLTMPL_HINT_MASK (1<<1)
///< tell host that channel is a mask

#define LIVIDO_CHNLTMPL_SAME_AS_SIZE (1<<2)
///< tell host that same_as refers to size

#define LIVIDO_CHNLTMPL_SAME_AS_PALETTE (1<<3)
///< tell host that same_as refers to palettes

/* IMPORTANT: Optional channels must always come at the end of channel templates.
	
*/

/// @}




// Values that denote end of channels list
#define LIVIDO_CHANNEL_TEMPLATE_END \
		{ \
		.name = NULL, \
		.palettes = NULL, \
		.same_as = 0, \
		.flags = 0, \
		.width = 0, \
		.height = 0, \
		}
	

/**
   @defgroup livido_channel_t Video channel 
   
   This is description of single channel. It relates to the channel templates

   Channels are setup by host BEFORE plugin's init() function is called. Therefore
   plugin at the init stage knows what kind of data it will be recieving.

   GOOD PRACTICE: livido-library.c provides a rutine lvd_check_channel_layout()
		  that checks if channel layout passed to plugin corresponds to
		  instance's template. Plugins should use it inside init() function.

   @{ */

typedef struct {
  /** the template that this channel is based upon 
  */ 
	livido_channel_template_t *based_on_template;

  /** If template of this channel allows it to be optional then setting
      this flag to LIVIDO_CHNL_OPTIONS_DISABLED will tell to the plugin
      that the channel is not used (other values in this structure except
      based_on_template are then meaningless)
      Will be used also for other things in future.
  */	
	uint32_t flags;             
 
  /** palette of the channel
      it is taken from one of the palettes provided by the template the channel was based on
  */
	livido_palette_t palette;   
	
  /** channel width and height in pixels
  */	
	uint32_t width; 
	uint32_t height; 

  /** u_shift and v_shift are  needed for 4:2:2, 4:2:0 modes and similar to know 
      how channels are aligned
  */
	
	uint32_t shift_u, shift_v; // this is needed for 4:2:2, 4:2:0 modes and similar to know how channels are aligned
 
  /** In packed modes rowstride[0] is the length of the row in bytes (including padding bytes)
      In planar modes every rowstride denotes the length of the plane in bytes!
     
     IMPORTANT: Every host has to set the rowstrides
     IMPORTANT: Every plugin has to honour the rowstrides
  */  	
	uint32_t rowstrides[6]; 

	char reserved[32];
} livido_channel_t;



// Option that can be set to 1 by host to tell that channel is disabled
#define LIVIDO_CHNL_OPTIONS_DISABLED	1

/// @}







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

   Frames in LiViDO are what is passed to process function. 
   They hold the pointer(s) to actual pixel data and pointer 
   to channel which holds geometrical and other information 
   needed for frame interpretation.
   
   
   @{ */
/////////////////////////////////////////////////////////////////


typedef struct {
	livido_channel_t *channel; ///< channel where interpretation of this data is available
	void *pixel_data[6];       ///< pixel data 
	char reserved[16];
} livido_frame_t;

#define LIVIDO_FRAME_END \
{ \
	.channel = NULL, \
	.pixel_data = {NULL,NULL,NULL,NULL}, \
}
///< define to mark the end of frames when the array is declared

/// @}

/**
   @defgroup livido_timecode_t Time code

   Livido only provides very very basic plugin awareness of time. 
   This is given trough timecode parameter being passed to 
   process() function of the plugin.
   
   Livido 1.0 does not hold timecode for every specific channel!

   IMPORTANT: livido_timecode_t is a double that denotes a time eplased since
   'play start' when doing realtime application (RT) or time since start of the timeline
   when doing non-realtime applicatons (NLE)
   
   GOOD PRATCTICE: some plugins might expect that the time is always in microseconds
   when providing time, provide it in microseconds

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

 // timecode in microseconds since 'play start' (RT) or start of the timeline (NLE)
typedef double livido_timecode_t;    

/// @}

// forward declaration
struct livido_instance_t;

/**
   @defgroup livido_get_keyframe_f Keyframe getting function

   IMPORTANT: This is important only for plugin/host writers wanting to do 
   advanced plugin-driven keyframing.
   
   This is generic definition of a function that returns a parameter set 
   at specific time.
  
   Advanced hosts provide two functions of this kind, one to fetch previous
   keyframe (according to timecode) and one to fetch the next one.
   
   host_data is internal pointer that is passed by host to  
   function interpolate_parameters
   
   position_timecode is the the timecode for which keyframe is being queried
   keyframe_timecode is a pointer where timecode of found frame is returned,
   if keyframe is not found -1 is returned.
   
   parameter_set is where keyframe is stored and param_size is auxilary, but
   mandatory parameter denoting the size of parameter set in bytes.
   
   IMPORTANT: This is important only for plugin/host writers wanting to do 
   advanced plugin-driven keyframing.
      
   


   @{ */
typedef int32_t (livido_get_keyframe_f) ( void *host_data,              // input
				      livido_timecode_t position_timecode,      //input
				      livido_timecode_t *keyframe_timecode,     //output
				      void *parameter_set,			// output
				      int param_number);                      //input



/// @}


/////////////////////////////////////////////////////////////////
/**
   @defgroup livido_instance_t 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 and setup by the host and passed to
   init of the plugin. After host deinits plugin, it is up to 
   the host to free the data that had been allocated.
   
   GOOD PRACTICE: Host authors should use LIVIDO_CREATE_INSTANCE
   and LIVIDO_FREE_INSTANCE to allocate data and free it.
   
   IMPORTANT: The initialization procedure from host side looks like this:
   1. LIVIDO_CREATE_INSTANCE (this allocates instance and space for channels)
   2. channels inside instance are setup according to templates and host's needs
   3. init() of the instance...

   IMPORTANT: ALL parameters of instance structure are set by host with
   two exceptions:
    - internal (host MUST NOT ever touch this)
    - error_message (set by instance on error)
   
   IMPORTANT: The list of parameters that the host can set after
   initialization:
    - frames_per_second
    - window_x1, window_y1, full_x, full_y
    - scale_x, scale_y
   But they must not be set during the call to process()!
   
   */

// all this, except "internal" is set BY HOST!
// Every proper Livido host must set all of this, so all plugins will work!
// Hosts not setting these to sane values risk that some plugins wont work
// or even worse - crush.


struct livido_instance_template_t;

typedef struct livido_instance_t {
  /** it must be allocated by the filter when the instance is created
      (before calling init(...))
  */
  livido_channel_t *in_channels; ///< arrays terminated by a channel with 
                                 ///palettes == NULL
  livido_channel_t *out_channels; ///< arrays terminated by a channel with 
                                 ///palettes == NULL


  float frames_per_second; // If host does not know, set it to some reasonable value to get maximum number of the plugins working
                           // if LVD_PROPERTY_FPS_NEEDED is set and host cannot provide fps... host should not try to use the plugin

  float scale_x, scale_y;   // if plugin advertizes LVD_PROPERTY_CAN_DO_SCALED, this can be used.  
  			  // Don't forget to reinit after setting this!
                          // leave it to 1.0 if not used...

  float window_x1, window_y1, full_x, full_y; // to be used if LVD_PROPERTY_CAN_DO_WINDOWED is true
					      // if host is not using can_be_windowed, it _must_ set full_x and full_y to zero

  int32_t hint_threads;  // number of threads plugin should use if it can... 
  			 // set it to 1 if you don't know (or better to the number of processors in your machine)
                         // plugin can safely ignore this, but all hosts have to set it

  ///< Pointer where host puts input parameters
  void *params_in;
  ///< Pointer where plugin should store output parameters on process call
  ///< If host sets it to null (default) plugin should not set output parameters
  void *params_out;

  void *internal; 	// filter's private buffers
  const struct livido_instance_template_t *my_template;       // pointer that should be casted to livido_class_t (but i have some problems)
 
  uint32_t error_code;      ///< error codes from init, process and deinit functions
  const char *error_message; ///< message about the error 

  char reserved[64];
} livido_instance_t;

#define LIVIDO_NO_ERROR				0
///< return code means no problem

/** This error usually indicates a poorly written plugin that uses
    static variables, or in some cases a plugin that needs to access a
    static resource like hardware which doesn't support multiple
    accesses */
#define LIVIDO_ERROR_TOO_MANY_INSTANCES		1
///< can't create: plugin allows only limited number of filter instances

#define LIVIDO_ERROR_MEMORY_ALLOCATION		2
///< memory allocation by the filter has failed (not enough memory?)

#define LIVIDO_ERROR_OOB_PARAMETERS		3
///< parameters passed to filter have been out of bounds

#define LIVIDO_ERROR_OOB_CHANNELS		4
///< plugin does not accept this kind of channel layout

/** If plugin deals with pheripheral hardware and there is something wrong this is returned
    IMPORTANT: in this case livido_filter_t::error_message should hold an explanation
    that host can present to the user. */
#define LIVIDO_ERROR_PHERIPHERY			5
///< an error occurred in handling peripheral hardware

#define LIVIDO_ERROR_INTERNAL			6
///< unspecified internal plugin error

#define LIVIDO_ERROR_AUXILIARY                  7
///< error in an auxiliary function

/// @}


///////////////////////////////////////////////////////////////////
/** 
    @defgroup filter_public Instance templates' public functions
    
    The following public functions are found in the instance template,
    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 instance template. The template will hold
    function pointers for the init() deinit() and process()
    functions.

    An host application should first setup the width, height and
    palette of the template, 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 every call 
    of process().

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

/**
    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
    @return error code
    */
typedef int32_t (livido_init_f) (livido_instance_t* instance);

/**
   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 int32_t (livido_deinit_f) (livido_instance_t*); 

/**
   Process input frames to output frames
   
   if plugin publicizes LVD_PROPERTY_INPLACE host can use the same 
   array as both  input and output!
   
   @param env filter instance
   @param instance pointer to the instance being used
   @param timecode timecode of the processing, 0 if host doesn't care
   @param in input frame(s) to be processed, NULL terminated
   @param out output frame(s) processed, NULL terminated
   @return error code */
typedef int32_t (livido_process_f) (livido_instance_t* instance,
				livido_timecode_t timecode,
				livido_frame_t *in, 
				livido_frame_t *out);


/**
   Function to query parameters. Called by both host.
   
   Plugins that do keyframing should implement it by themselves, 
   this is the function that provides interpolating.
     
   This is also directly used by hosts that support keyframing, to 
   fetch (interpolated if plugin supports it) values of parameters 
   at some point in time.
   
   In hosts supporting keyframes call to interpolate_params(...) 
   is the called before every process(...) function since it
   fetches parameters needed for processing.
   
   @param env filter instance
   @param instance instance being used
   @param timecode timecode for which we want to get parameters
   @param parameters where to place parameters
   @return error code */
typedef int32_t (livido_interpolate_parameters_f) (
				      livido_get_keyframe_f *get_prev_keyframe ,
				      livido_get_keyframe_f *get_next_keyframe ,
				      void *host_data,
				      livido_timecode_t timecode,
				      void *parameters);
///@}
















/** 
    @defgroup property Filter properties
    
    Properties of a filter define aspects of its functioning,
    they are flags set on the instance template, 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 LVD_PROPERTY_REALTIME (1<<0x0) 
///< realtime filter property

/**
   If this property is set, the filter can do inplace operations then
   host can use plugin process() function in a way to have the same
   input and output channels
   If plugin advertizes this capability, it HAS to have first 
   output channel connected to the first input channel (same_palette and same_size)
*/
#define LVD_PROPERTY_CAN_DO_INPLACE (1<<0x1)
///< inplace filter property


// plugin knows how to scale the parameters when drawing previews/thumbnails 
// host can use scale_x and scale_y in this case 
#define LVD_PROPERTY_CAN_DO_SCALED (1<<0x3) 


// plugin knows how to operate on window of frame (adjusting parameters accordingly)
// window is denoted as window_x1, window_y1 for upper left corner of the window
// and full_x and full_y give the total size of the frame as it was before cropping
// lower right corner can be caluclated by adding window_x1 to channel width... and the same for height
#define LVD_PROPERTY_CAN_DO_WINDOWED (1<<0x4) 


// plugin can do automation by itself (keyframming)
#define LVD_PROPERTY_SELF_AUTOMATION (1<<0x5)


// plugin absolutely needs frames_per_second information, don't try to use it without
#define LVD_PROPERTY_FPS_NEEDED (1<<0x6) 

// should the init(..) be called by host after it resizes any channel (and before it calls process)
#define LVD_PROPERTY_STATIC_CHANNEL_SIZES (1<<0x7)

// should the init(..) be called by host after it changes palettes for any channel (and before it calls process)
#define LVD_PROPERTY_STATIC_CHANNEL_PALETTES (1<<0x8)
///@}







/////////////////////////////////////////////////////////////////
/**
   @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* These are just templates of parameter scheme 
   and not place to store parameters.
   
   @{ */
/////////////////////////////////////////////////////////////////

#define LVD_PARAM_SWITCH	1  ///< on/off switch
#define LVD_PARAM_NUMBER	2  ///< double value
#define LVD_PARAM_RGBA		3  ///< color triplet for red green and blue (16 bits per channel)
#define LVD_PARAM_COORD2D	4  ///< 2d cartesian coordinates (double)
#define LVD_PARAM_STRING	5  ///< string of maximum length = LIVIDO_STRING_SIZE
#define LVD_PARAM_STRINGLIST	6  ///< strings of maximum length = LIVIDO_STRING_SIZE, one has to be picked
#define LVD_PARAM_POINTER	7  ///< pointer to custom data buffer
#define LVD_PARAM_END 		0  ///< end of parameter declaration



// GOOD PRACTICE: If possible, try avoiding use of LVD_PARAM_FLAG_NEEDS_INIT since 
// there are good chances that hosts will be buggy and not support it
#define LVD_PARAM_FLAG_NEEDS_INIT (1<<0x0) // need to re-init when value changes

// IMPORTANT: There can be AT MOST ONE parameter with this flag in parameter set
// and in case it exists, it has to be of type LVD_PARAM_NUMBER and has to be FIRST parameter
// inside a parameter set
#define LVD_PARAM_FLAG_TRANSITION (1<<0x1) // min is no transition, max is full

// This means if host takes upon himself the keyframing, it should keyframe this paramter
#define LVD_PARAM_FLAG_KEYFRAMED  (1<<0x2) ///< host should keyframe this parameter

// This parameter should generally not be present in the UI, host should know better
// what to do with it. This is used for auxilary parameters calculated from others when keyframing
#define LVD_PARAM_FLAG_HIDDEN (1<<0x3) 

#define LIVIDO_STRING_SIZE 	1024          // makes me feel better than 256 ... for titling

typedef int32_t					lvd_type_switch;
typedef double					lvd_type_number;
typedef struct { float r,g,b,a; }	 	lvd_type_rgba; // values for each channel are between 0.0 and 1.0
typedef struct { double x,y; }			lvd_type_coord2d;
typedef char					lvd_type_string[LIVIDO_STRING_SIZE];
typedef int					lvd_type_stringlist;
typedef void *					lvd_type_pointer;


#define LIVIDO_PARAM_SIZE(p) ( \
	((p) == LVD_PARAM_SWITCH)        ? sizeof(lvd_type_switch) : \
        ((p) == LVD_PARAM_NUMBER)     	 ? sizeof(lvd_type_number) : \
        ((p) == LVD_PARAM_RGBA)          ? sizeof(lvd_type_rgba): \
        ((p) == LVD_PARAM_COORD2D)       ? sizeof(lvd_type_coord2d): \
        ((p) == LVD_PARAM_STRING)        ? sizeof(lvd_type_string): \
        ((p) == LVD_PARAM_STRINGLIST)    ? sizeof(lvd_type_stringlist): \
        ((p) == LVD_PARAM_POINTER)       ? sizeof(lvd_type_pointer) : 0)


/**
   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

                              /// GOOD PRACTICE: hints should use the keyword system, e.g:
                              /// layout|p1|fill|p2\n
                              /// special|aspect|1|2
                              /// there will be a separate document about the hint system

const	int	type;	      ///< the parameter type (see livido_param_type_enum)
const	void	*choice_list; ///< choices that are available. Most used for Stringlist parameter
		              ///< IMPORTANT: choices has to be NULL for all parameters not using it (currently for all but stringlist)!
const   int     decimals;     ///< decimal places to display after the floating point (for LVD_PARAM_NUMBER)
const   double  step_size;    // size of step when having LVD_PARAM_NUMBER
const	int	flags;	      // flags of parameter (LVD_PARAM_FLAG_*)
	int	size;         // Size of the paramter data in bytes
	int	offset;	      // Byte offset of parameter inside the block
			      // Both are not constant because it is set by macro LIVIDO_FILL_OFFSETS 
	char	reserved[32];	
} livido_parameter_template_t;


/*
Useful comments about livido_parameter_template_t:

name: should be short. lowercase. do not put in the words like
      "plugin" or "filter", but rather the name of the thing
      
description: this is not the help string. it should explain what
             the plugin does, not what its parameters are
             warnings can go inside
             it can be multilined!
         
hint: has not been defined yet. Lives already uses this is some specific way

type: one of livido_param_type_enum

min, max: minimal and maximal values for number parameter
	  currently use is defined only whe type = lvd_type_number
          Host should NEVER set values out of this range
          Automatic check is available in livido-library.c
          lvd_check_parameter_boundaries();
         
 
def: pointer to default value of type type
     has to be always set to the valid value!

choices: pointer to the list of possible values
	 currently the use is defined only when type = lvd_type_stringlist 

decimals: number of decimals the GUI should show for this variable
	  currently use is defined only when displaying numerical values
	  
step_size: size of step when type = lvd_type_string

flags: bitwise union of LVD_PARAM_FLAG_* 
       denoting the properties of this parameter
       
offset: offset of this parameter inside parameter block


*/

///< small define to mark the end of parameters when the array is declared

#define LIVIDO_PARAM_END \
{ NULL, NULL, NULL, LVD_PARAM_END, NULL, 0, 0., 0, 0 }


// IMPORTANT: Following defines should be used by host only, since there is no need
// to typecast or do indexed access to parameters inside a plugin

// Defines to cast pointer into the param

#define LVD_CAST_VOID(pointer)  ((void *)(pointer))  
#define LVD_CAST_SWITCH(pointer)  ((lvd_type_switch *)(pointer))  
#define LVD_CAST_NUMBER(pointer) ((lvd_type_number *)(pointer)) 
#define LVD_CAST_RGBA(pointer) ((lvd_type_rgba *)(pointer))
#define LVD_CAST_COORD2D(pointer) ((lvd_type_coord2d *)(pointer))
#define LVD_CAST_STRING(pointer) ((lvd_type_string *)(pointer))
#define LVD_CAST_STRINGLIST(pointer) ((lvd_type_stringlist *)(pointer))
#define LVD_CAST_POINTER(pointer) ((void **)(pointer))

// Defines to set/get one of the params from the block

#define LVD_GET_VOID(cl, paramset, number) LVD_CAST_VOID(((char *)paramset) + cl->in_parameter_templates[number].offset)
#define LVD_GET_SWITCH(cl, paramset, number) LVD_CAST_SWITCH(((char *)paramset) + cl->in_parameter_templates[number].offset)
#define LVD_GET_NUMBER(cl, paramset, number) LVD_CAST_NUMBER(((char *)paramset) + cl->in_parameter_templates[number].offset)
#define LVD_GET_RGBA(cl, paramset, number) LVD_CAST_RGBA(((char *)paramset) + cl->in_parameter_templates[number].offset)
#define LVD_GET_COORD2D(cl, paramset, number) LVD_CAST_COORD2D(((char *)paramset) + cl->in_parameter_templates[number].offset)
#define LVD_GET_STRING(cl, paramset, number) LVD_CAST_STRING(((char *)paramset) + cl->in_parameter_templates[number].offset)
#define LVD_GET_STRINGLIST(cl, paramset, number) LVD_CAST_STRINGLIST(((char *)paramset) + cl->in_parameter_templates[number].offset)
#define LVD_GET_POINTER(cl, paramset, number) LVD_CAST_POINTER(((char *)paramset) + cl->in_parameter_templates[number].offset)



///@}




/**
   @defgroup instance_template Instance template

   The template 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 template 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 template.
    
   @{ */

typedef struct livido_instance_template_t {

  char *name; ///< name of filter
  char *author; ///< author of filter
  char *description; ///< long text description
  char *licence; ///< licence of the plugin, should be something like "GPL", "BSD", "Public domain", "MS EULA"...
  int version; ///< filter version
  
  int livido_api_version; ///< version of the livido api used
  
  int property;
  ///< filter properties LVD_PROPERTY_*
  
  livido_parameter_template_t	*in_parameter_templates;
  ///< NULL terminated array of input parameter descriptions
  ///< GOOD PRACTICE: Never change the parameter order between different versions of plugin. This might annoy many hosts.

  livido_parameter_template_t	*out_parameter_templates;
  ///< NULL terminated array of ouput parameter descriptions
  ///< IMPORTANT: Can be NULL if plugin does not support output parameters
  ///< GOOD PRACTICE: Never change the parameter order between different versions of plugin. This might annoy many hosts.
 
  ///< Pointers to memory blocks of min, max and default parameter sets
  void *params_in_min;
  void *params_in_max;
  void *params_in_def;

  ///< Pointers to memory blocks of min and max for output parameters
  void *params_out_min;
  void *params_out_max;

  ///< pointer to array of pointers to parameters sets (array is null pointer terminated)
  ///< IMPORTANT: set to NULL if you don't offer the presets
  void **params_in_sets; 
  
  ///< size of the parameter set in bytes
  ///< GOOD PRACTICE: should automatically setup by LIVIDO_FILL_OFFSETS called from livido_setup()
  int32_t params_in_size; 
  int32_t params_out_size; 


  
  livido_channel_template_t *in_channel_templates;  // in_channels template
                                  ///< arrays terminated by a channel with 
                                  ///palettes == NULL

  livido_channel_template_t *out_channel_templates;  // out_channels template
                                   ///< arrays terminated by a channel with 
                                   ///palettes == NULL
 

  /* 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
  livido_interpolate_parameters_f 	*interpolate_parameters;
  ///< fills the parameter structure with calculated parameters at specific timecode
  
  char *hints; // hints about presenting of the plugin

  void *extra; ///< extra data pointer reserved for future use

  char reserved[64];
  
} livido_instance_template_t;

#define LIVIDO_INSTANCE_TEMPLATE_END \
{ \
	.name = 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 pointer to array of instance templates terminated by .name == NULL

   @brief Setup the global environment of the plugin.
   @return NULL terminated array of instance templates available */
typedef livido_instance_template_t *(livido_setup_f) (void);



/// @}


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

   - allocate the space needed for parameters
   - set the filter parameters to the default values
   - allocate the space for channel info
   - sets up the base_channels ...
   - sets get_prev_keyframe and get_next_keyframe 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 instance template
   @param cl instance_template
   @param inst pointer where to store the new filter instance */



/* GOOD PRACTICE:
	When starting to write a host, use this macro to set you up
	basic parameters
*/
#define LIVIDO_COPY_DEFAULT_PARAMETERS(insttmpl, parameter_set) \
{ \
 memcpy(parameter_set, insttmpl->params_in_def, insttmpl->params_in_size); \
}


/* IMPORTANT:
	Function always called from livido_setup() that sets the sizes of 
	parameters that are not custom
	
*/
#define LIVIDO_FILL_SIZES(insttmpl) \
{ int c; int lastsize = 0;\
 for(c=0; insttmpl.in_parameter_templates[c].name != NULL; c++) { \
 	int param_size = LIVIDO_PARAM_SIZE(insttmpl.in_parameter_templates[c].type); \
 	if (param_size != 0) \
		insttmpl.in_parameter_templates[c].size = param_size; \
	lastsize = insttmpl.in_parameter_templates[c].offset + param_size; \
 } \
 insttmpl.params_in_size = lastsize; \
 lastsize = 0; \
 for(c=0; insttmpl.out_parameter_templates[c].name != NULL; c++) { \
 	int param_size = LIVIDO_PARAM_SIZE(insttmpl.out_parameter_templates[c].type); \
 	if (param_size != 0) \
		insttmpl.out_parameter_templates[c].size = param_size; \
	lastsize = insttmpl.out_parameter_templates[c].offset + param_size; \
 } \
 insttmpl.params_out_size = lastsize; \
}


// For host: basic instance structure setup (for simple hosts)
// for hosts using plugins with optional channels.. disabled should be set to one
#define LIVIDO_CREATE_INSTANCE_MAIN(insttmpl,inst) \
{ inst = (livido_instance_t *)malloc(sizeof(livido_instance_t)); \
 inst->internal = NULL; \
 inst->frames_per_second = 25.0; \
 inst->scale_x = 1.0; \
 inst->scale_y = 1.0; \
 inst->full_x = 0.0; \
 inst->full_y = 0.0; \
 inst->hint_threads = 1; \
 inst->my_template = insttmpl; \
 inst->error_message = NULL; \
 inst->params_out = NULL; \
 inst->error_code = LIVIDO_NO_ERROR; \
 inst->error_message = NULL; \
 inst->params_in = (void *)malloc(insttmpl->params_in_size); \
 inst->params_out = (void *)malloc(insttmpl->params_out_size); \
}




#define LIVIDO_CREATE_INSTANCE(insttmpl,inst) \
{ int c; \
  livido_channel_t *in_array,*out_array; \
  LIVIDO_CREATE_INSTANCE_MAIN(insttmpl,inst); \
  for(c=0;insttmpl->in_channel_templates[c].name!=NULL; c++);  \
  in_array = (livido_channel_t *) malloc(++c*sizeof(livido_channel_t)); \
  for(c=0;insttmpl->in_channel_templates[c].name!=NULL; c++) { \
	in_array[c].based_on_template = &(insttmpl->in_channel_templates[c]); \
	in_array[c].flags = 0; \
	}\
  in_array[c].based_on_template = NULL; \
  for(c=0;insttmpl->out_channel_templates[c].name!=NULL; c++);  \
  out_array = (livido_channel_t *) malloc(++c*sizeof(livido_channel_t)); \
  for(c=0;insttmpl->out_channel_templates[c].name!=NULL; c++) { \
	out_array[c].based_on_template = &(insttmpl->out_channel_templates[c]); \
	out_array[c].flags = 0; \
	}  \
  out_array[c].based_on_template = NULL; \
  inst->in_channels=in_array; \
  inst->out_channels=out_array; \
}



#define LIVIDO_CREATE_INSTANCE_C(cl,inst,in_channs,out_channs) \
{ int c;\
livido_channel_t *in_array,*out_array; \
LIVIDO_CREATE_INSTANCE_MAIN(cl,inst);\
for(c=0;in_channs[c].based_on_template->name!=NULL; c++);  \
in_array=(livido_channel_t *)malloc(++c*sizeof(livido_channel_t)); \
for(--c;c>=0;c--) \
  { \
    memcpy(&in_array[c],&in_channs[c],sizeof(livido_channel_t)); \
  } \
for(c=0;out_channs[c].based_on_template->name!=NULL; c++);  \
out_array=(livido_channel_t *)malloc(++c*sizeof(livido_channel_t)); \
for(--c;c>=0;c--) \
  { \
    memcpy(&out_array[c],&out_channs[c],sizeof(livido_channel_t)); \
  } \
inst->in_channels=in_array; \
inst->out_channels=out_array; \
}




// called from host, for freeing the instance
#define LIVIDO_FREE_INSTANCE(cl,inst) \
{ \
free (inst->params_in); \
free (inst->params_out); \
free (inst->in_channels); \
free (inst->out_channels); \
free (inst); \
}



#endif // __LIVIDO_H__




// Things that are solved by Livido 1.0 (if host and plugin support it):

// Frames with rowsize != width * bytes_per_pixel
// Colormodes that need channel offsets (YUV 4:2:2, 4:2:0...) for proper presentation
// Channel dependencies on other channels for palette and size
// Plugin can have sense of video time (timecodes)
// Plugin can know frame numbers (if host wants to set fps correctly)
// Plugin can have internal state and do accumulation of data
// Clear separation of channel_template, channel and frame
// The easiest possible plugin parameter handling (using internal struct to typecast)
// Easy plugin-driven keyframming of paramter sets
// Easy host-driven keyframming of parameter sets 
// Multi-palette support
// Inplace support 
// Preview size / thumbnail rendering (automatic parameter adjustment)
// Windowed rendering (automatic parameter adjustment)
// no memory allocations need to be done in simple plugins
// API that is multithreading-proof (no race conditions)
// 'Natural' writing of stateless plugins
// Advanced plugin can have internal state and do accumulation of data
// parameter type listbox (trough stringlists)
// support for predefined parameter sets offered by the plugin

// Things left for Livido 2.0, 3.0, custom extensions or neverland:

// - Dynamic parameters (number of parameters not being constant over class/instance/time)
// - Text based capabilities querying (both ways)
// - Pull method
// - Caching (in relation to pull method)
// - Copy-on-write
// - 'repeatable' channel descriptions
// - out colormodes depending in complex ways on in colormodes
// - frame size constraints (except fixed frame size which can already be done)
// - Every separate parameter being keyframmed at different points in time  when using plugin driven keyframming
// - choosing of interpolation methods for specific parameters  (for plugin driven keyframming)
// - GUI descriptions in XML, .glade2 or similar
// - handling of GUI by the plugin (via OpenGL canvas or X window)
// - complex constraints for complex parameter types (colors, COORD_2D)
// - even more complex parameter types (meshes, nurbs, 3d)
// - combobox parameter set (custom text + predefined choices)
// - explaining to the host complex interparameter dependencies
// - audio routing through livido API
// - network transparency
// - quality modes
// - timing guarantees, guaranted timeouts and host-driven-async-abort



// new things in 1.2
// fixed parameter sizes of rgb24 and rgba32 (use char instad of int in livido_param_size)
// Thanks to Carlo E. Prelz fixed the problems with my_class having to be void *
// added LVD_PROPERTY_CAN_DO_WINDOWED for window operation
// renamed LVD_PARAM_DATA to LVD_PARAM_POINTER (it is now more clear what it is)
// added typedefs lvd_type_* to match params...
// changed coord2d to float types... to be more universal
// added offsets to livido_parameter_description_t in order to access parameters easier
// added defines to typecast to parameters (LVD_GET_AS_*) (for use by host)
// added defines to access specific parameters in the param block (LVD_PARAM_*) (for use by host)
// added LIVIDO_FILL_OFFSETS to be called on setup by plugin to init the offsets automagically
// renamed based_on_channel to based_on_template


// new things in 1.3
// rgb24 and rgb32 moved to uint16_t ... for greater range
// coord2d moved to double
// removed LVD_PARAM_INTEGER and LVD_PARAM_FLOAT in favor of LVD_PARAM_NUMBER
// added step_size to parameter (to be used for LVD_PARAM_NUMBER)
// in support library ... added lvd_free_params(...)
// in support library, dump rutines now honor decimals for LVD_PARAM_NUMBER
// added lvd_value_to_text that puts any parameter into human readable form
// minor fixes all around
// comment fixes
// reorganization of the code in both sample plugins (shuffling it around)
// added LVD_PROPERTY_RESIZE since it got somehow left out
// changed name of inplace property to LVD_PROPERTY_CAN_DO_INPLACE

// new things in 1.4
// added hints to livido_class_t (i intentionally left out the "window_" part of the name to stay more general)
// added LVD_PARAM_STRINGLIST for passing lists. the type resembles the pointer the most
// added YUYV and UVYV colormodels
// fixed some bugs in LIVIDO_PALETTE_BYTES
// aded BGR888 and ALPHAFLOAT colormodels 
// changed all end-of templates check to .palette == LVD_PALETTE_END
// added missing palettes to lvd_get_palette_name
// fixed LVD_GET_AS_POINTER to return pointer to pointer
// enabled LVD_PROPERTY_CAN_DO_WINDOWED, to complement _CAN_DO_SCALED
// fixed lvd_param_pointer to return pointer to pointer
// did full LVD_PARAM_STRINGLIST testing (by fade_plugin.c)


// new things in 1.5
// make it C++ compatible (so g++ can be used for both livido.h and livido-library.c)
// added const to all livido_class_t * definitions in livido-library (since classes don't change)
// reshuffled the keyframing rutines, so now keyframing can be used on class level instead of instance level
// this means a bit more complex definitions of two functions, but they are hidden from SIMPLE plugins/hosts anyway
// renamed _STUPID_ macros to more acceptable _SIMPLE_
// changed _GET_ to _PLUGIN_ and _SET_ to _HOST in _SIMPLE_ macros, so it is more logical where to use them
// changed testhost.c so it only tests with complex methods, not SIMPLE (yes, this works even against simple plugins)
// reshuffled some code in testhost.c so it is obvious when we are testing class functionality and when instance functionality
// named fade_plugin_simple to "Fade plugin simple" so both examples differ in name
// New convention: environment variable LIVIDO_PATH points to directories with plugins
// livido_channel_templates_t are ended by palette = NULL
// added constraint: optional channels must always be at the end of channel templates!
// Extensive documentation added
// Default values work for stringlists also, since choices have been split into 
// different variable
// process function now gets just one pointer to in and out frame arrays that are sentinel terminated


// new things in 1.6
// demand that livido_parameter_description_t.choices = NULL for everything but stringlist parameter type
// (this means untill we define what non-null value means for other types)


// new things in 1.7
// minimum, maximum and default are implemented as parameter sets
// new pointer in livido_class_t that points to array pointers to presets (terminated with null pointer)
// added new variabile to class - parameter_size = size of parameter set in bytes, this means less code all around
// added basic self test to fade_plugin_* that tells if parameter description matches internally used parameters' structure


// new things in 1.8
// merge with salsamans scratch1 and scratch2
// added palette LVD_PALETTE_RGB565 as 20
// changed ALPHAxx palettes to Ax and added A4, A2, A1, updated appropriate macros
// added flags to livido_channel_template_t and removed optional
// removed same_as_palette and same_as_size and added same_as to livido_channel_template_t
// definition for flags:
// added LIVIDO_CHANNEL_SAME_AS_SIZE and LIVIDO_CHANNEL_SAME_AS_PALETTE
// added LVD_CHANNEL_HINT_MASK and LVD_CHANNEL_OPTIONAL
// removed LIVIDO_PROPERTY_HOST_CAN_RESIZE and added LIVIDO_PROPERTY_STATIC_PALETTES and LIVIDO_PROPERTY_STATIC_SIZES
// changed LVD_PARAM_* to defines (from enums)
// changed cpus to hint_threads in livido_instance_t
// changed in_channels to in_channel_templates, the same for out
// LVD_PROPERTY_TRANSITION removed
// changed parameter_descriptions to in_parameter_descriptions in livido_class_t
// added out_parameter_descriptions in livido_class_t
// added params_out to livido_instance_t, set to NULL inside LIVIDO_CREATE_INSTACE_MAIN
// removed disabled and added flags to livido_channel_t
// added define for LIVIDO_CHN_OPTIONS_DISABLED (for livido_channel_t.flags)
// changed macros LVD_GET_AS_*  to LVD_CAST_*
// changed macros LVD_PARAM_*(x,x,x) to LVD_GET_*(x,x,x)k 
// LIVIDO_CREATE_INSTANCE bug fixed
// updated 'conformance suit'
// added int error_code to livido_instance_t
// added initializors for error_code and error_message to LIVIDO_CREATE_INSTANCE_MAIN
// added LIVIDO_ERROR_* error codes and explanations
// added new palette types to livido-libarary 
// added RGBX8888 and RGB565 support to sample plugins (code by Carlo E. Prelz)
// added capability to return multiple classes and LVD_CLASS_END


// new things in 1.9
// fixed a small bug in livido-library.c in dump rutines max was dumped instead of default
// everything compiles with -Wall -pedantic -std=c99 without any warnings (demand from Niels)
// changed livido_class_t to livido_instance_template_t and all other occurances of class (Jaromil's naming)
// split interpolate functionality totaly away from process_frame (as discussed with Salsaman)
// removed host_data, get_prev_keyframe and get_next_keyframe from livido_instance_t 
// removed LIVIDO_SIMPLE_HOST_PARAMETERS and LIVIDO_SIMPLE_PLUGIN_PARAMETERS
// added LVD_PARAM_FLAG_HIDDEN to denote non UI parameters
// removed both rgba32 and rgb24 in favor of rgba (being floating point) paramter
// renamed get_parameters to interpolate_parameters
// changed get_keyframe function so it also has the parameter number argument (to be able to fetch each parameter separately)
// removed LIVIDO_PALETTE_BYTES (same as jaromil's version), fixed bug in LIVIDO_PALETTE_BITS
// rename livido_parameter_description_t to livido_parameter_tempalte_t (Jaromil's naming)
// added licence field to livido_instance_template_t
// added reserved bytes at the end of each structure for forward compatibility
// changed stringlist to the fully indexed mode

// new things in 2.0
// added size value to livido_parameter_template_t and changed LIVIDO_FILL_OFFSETS accordingly
// fixed missing .licence = "Public domain" in both example plugins
// testhosts provide more precise answer when dlopen fails
// added mandatory .offset setting to parameter templates to avoid errors about alignment assumptions
// renamed LIVIDO_FILL_OFFSETS to LIVIDO_FILL_SIZES since this is what it does
// refformating of code, celeaning it up
// removed plugin dependecny on error-checking functions from the livido-library





