/*
    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 GNU/Linux
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 GNU/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 GNU/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 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.1 of the License, or (at your option) any later version.

   LiViDO 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.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with this source code; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA


   LiViDO is developed by:

   Denis "Jaromil" Rojo - http://freej.dyne.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

   Silvano "Kysucix" Galliani - http://freej.dyne.org

   reviewed with suggestions and contributions from:

   Kentaro Fukuchi - http://megaui.net/fukuchi

   Jun Lio - http://www.malib.net

   Carlo Prelz - http://www2.fluido.as:8080

*/

#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: livido.h 64 2004-11-14 22:53:21Z jaromil $"
///< last modification


#define LIVIDO_HEADER_VERSION 1


struct livido_instance_template;
typedef struct livido_instance_template livido_instance_template_t;

struct livido_channel_template;
typedef struct livido_channel_template livido_channel_template_t;

struct livido_channel;
typedef struct livido_channel livido_channel_t;

struct livido_parameter_template;
typedef struct livido_parameter_template livido_parameter_template_t;

struct livido_parameter;
typedef struct livido_parameter livido_parameter_t;

struct livido_frame;
typedef struct livido_frame livido_frame_t;

struct livido_instance;
typedef struct livido_instance livido_instance_t;



/**
    @defgroup livido_palette Palettes

    Livido Palettes, also known as supported colorspace schemes

    In Livido a filter can specify more than one supported palette.

    Float RGBA 128bit is the mandatory palette, so that for each
    plugin we can have a pure numerical clear reference
    implementation.

    Each plugin can then offer support for other optional palettes,
    plugin programmers are strongly encouraged to re-contribute such
    additions to plugins so that we can keep our main repository up to
    date.
    
    If you want to add a palette to this list please contact us on
    <piksel-dev ...\\@//... bek.no>
    anyway you can add custom palettes above the 2048 number
    for your hacking convenience.

    GUIDELINE: Palette names should be unambiguous. We will add them
    when we have real applications using them, not because of
    theoretical ideas.

    @{ */


#define LIVIDO_PALETTE_RGB24               1
#define LIVIDO_PALETTE_RGB888		   1
#define LIVIDO_PALETTE_RGB32               2
#define LIVIDO_PALETTE_RGBA8888		   2
#define LIVIDO_PALETTE_RGB161616	   3
#define LIVIDO_PALETTE_RGBA16161616	   4
#define LIVIDO_PALETTE_YUV888		   5
#define	LIVIDO_PALETTE_YUVA8888		   6
#define	LIVIDO_PALETTE_YUV161616	   7
#define	LIVIDO_PALETTE_YUVA16161616	   8
#define	LIVIDO_PALETTE_YUV422P		   9
#define LIVIDO_PALETTE_YUV420P		   10
#define LIVIDO_PALETTE_YUV444P		   11
#define LIVIDO_PALETTE_A8		   12
#define LIVIDO_PALETTE_A16		   13
#define LIVIDO_PALETTE_RGBFLOAT		   14
#define LIVIDO_PALETTE_RGBAFLOAT	   15
#define LIVIDO_PALETTE_AFLOAT              16
#define LIVIDO_PALETTE_BGR888	           17
#define LIVIDO_PALETTE_YUYV8888	           18
#define LIVIDO_PALETTE_UYVY8888		   19
#define LIVIDO_PALETTE_RGB565		   20
#define LIVIDO_PALETTE_RGBX8888		   21
#define LIVIDO_PALETTE_A4		   22
#define LIVIDO_PALETTE_A2		   23
#define LIVIDO_PALETTE_A1		   24

#define  LIVIDO_PALETTE_FIRST_CUSTOM 2048


#define LIVIDO_PALETTE_END         (0x0)




#define LIVIDO_PALETTE_BITS(p) ( \
        (p == LIVIDO_PALETTE_RGBAFLOAT)    ?  128 : \
        (p == LIVIDO_PALETTE_RGBFLOAT)     ?  96  : \
        (p == LIVIDO_PALETTE_RGBA16161616) ||       \
        (p == LIVIDO_PALETTE_YUVA16161616) ?  64  : \
        (p == LIVIDO_PALETTE_RGB161616)    ||       \
        (p == LIVIDO_PALETTE_YUV161616)    ?  48  : \
        (p == LIVIDO_PALETTE_RGBA8888)     ||       \
        (p == LIVIDO_PALETTE_RGBX8888)     ||       \
        (p == LIVIDO_PALETTE_YUVA8888)     ||       \
        (p == LIVIDO_PALETTE_AFLOAT)	   ||       \
        (p == LIVIDO_PALETTE_YUV444P)      ?  32  : \
        (p == LIVIDO_PALETTE_RGB888)       ||       \
        (p == LIVIDO_PALETTE_BGR888)       ||       \
        (p == LIVIDO_PALETTE_YUV888)       ?  24  : \
        (p == LIVIDO_PALETTE_YUV422P)      ||       \
        (p == LIVIDO_PALETTE_YUYV8888)     ||       \
        (p == LIVIDO_PALETTE_UYVY8888)     ||       \
        (p == LIVIDO_PALETTE_RGB565)       ||       \
        (p == LIVIDO_PALETTE_A16)	   ?  16  : \
        (p == LIVIDO_PALETTE_YUV420P)      ?  12  : \
        (p == LIVIDO_PALETTE_A8)	   ?  8   : \
        (p == LIVIDO_PALETTE_A4)	   ?  4   : \
        (p == LIVIDO_PALETTE_A2)	   ?  2   : \
        (p == LIVIDO_PALETTE_A1)	   ?  1   : 0)
///< macro to check how many bits is a palette

#define LIVIDO_PALETTE_IS_PLANAR(p) ( \
        (p == LIVIDO_PALETTE_YUV444P)      ||       \
        (p == LIVIDO_PALETTE_YUV422P)      ||       \
	(p == LIVIDO_PALETTE_YUV420P)	   ?  1   : 0 )
///< macro to check if the palette is plannar

#define LIVIDO_PALETTE_IS_CUSTOM(p) ( \
        (p&2048) ? 1 : 0 )
///< macro to check if the palette is custom

/// @}


/////////////////////////////////////////////////////////////////
/**
   @defgroup livido_channel_template_t Channel template

   Channels templates are provided by the plugin as a template to form
   channels (::livido_channel) inside a filter (::livido_instance).

   They come to the host as part of the filter template
   (::livido_instance_template) received when the ::livido_setup_f()
   function is first retreived with dlopen() and called.

   These fields contain pointers to the first input and output
   channels respectively, which are the initial elements of linked
   lists.

   When the host receives the *in_channel and *out_channel channel
   template 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.

   Assuming one of the palettes in the list is acceptible to the host,
   the host indicates this by copying the value of palette in the
   channel (::livido_channel) implementation hold by the filter
   (::livido_instance).

   If a channel is optional, the plugin indicates this by setting the
   #LIVIDO_CHANNEL_OPTIONAL flag. The host can indicate not using the
   channel by setting the flag #LIVIDO_CHANNEL_DISABLED inside the channel
   implementation hnold by the filter.

   The mandatory task for the host is to set the channel width and
   height. If livido_channel_template::width is nonzero, the only
   possible size that channel can take is denoted as width and heigth
   parameters of the template.

   If the filter template flag #LIVIDO_PROPERTY_HOST_CAN_RESIZE is not
   set, host can resize channel and recall init()

   If the filter template flag #LIVIDO_PROPERTY_HOST_CAN_CHANGE_PALETTE is
   set, host can change palette and recall init()

   If the "same_as" field is set for any of the channels, the host
   should check that palette and size matches with the other channel,
   depending on the setting of #LIVIDO_CHANNEL_SAME_AS_SIZE or
   #LIVIDO_CHANNEL_SAME_AS_PALETTE.


   @{ */




/**
   This structure is a template describing every single possible
   channel, it is held by the filter template and used to put create
   ::livido_channel structures passed back to plugin at
   initialization of the filter

   IMPORTANT: Host NEVER changes any part of this structure

   @brief Template provided by plugin to describe in/out channels
*/

struct livido_channel_template {

  /**
     This field can be set to the name of the channel (e.g. "Input 1").

     GOOD PRACTICE: Avoid using words like "channel" inside the name,
     since it is implicit. */
  char *name; ///< name of the channel

  /**
      See further down for a list of possible flags.
      If channel is optional, host is allowed not to use it.
      IMPORTANT: Optional channels ALWAYS come at the end of the channel list */
  int flags; ///< flags for this channel (read-only)

  /**
     The plugin sets this pointer to an array of palettes it can
     accept on this channel, in order of preference, NULL terminated.

     Before initialization, the host will set his selected value(s) in
     order of preference inside the channel (::livido_channel) hold by
     the filter (::livido_instance) */
  int *palettes; ///< list of palettes supported by plugin

  /**
     The plugin can use this field to tell the host that the settings
     of palette choice and size (width/height) 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 X means "must match input channel X"
     - a negative value X means "must match output channel X"
     - a setting of ZERO implies free choice for palette and size settings.

     IMPORTANT: this way it can only reference channels that have
     serial numbers smaller then current. in case of output channels
     they can also reference all input channels, but input channels
     cannot refer to output channels.
     This way we avoid circular dependencies! */
  int same_as; ///< size and palette must be the same as another channel


  /**
     Channel width and height, the plugin will leave those to 0 if host
     can choose them arbitrarily.

     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 */
  int width;  ///< the only width supported by plugin, 0 if any
  int height; ///< the only height supported by plugin, 0 if any

  struct livido_channel_template *next;
  ///< pointer to the next element in the list, NULL if end

  char reserved[64]; ///< reserved space for binary compatibility thru versions

};

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

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

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

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

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

#define LIVIDO_CHANNEL_RESIZABLE (1<<4)
///< tell host that frames can be resized while processing


/// @}












///////////////////////////////////////////////////////////////////
/**
    @defgroup filter_public Public functions

    The following public functions are found in the filter 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 filter template. The template will hold function
    pointers for the ::livido_init_f() ::livido_deinit_f() and
    ::livido_process_f() functions.

    An host application should first setup the width, height and
    palette of the filter, then it can proceed to initialize the
    filter.

    The init() must be called in order to create a 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 allocated filter which
    has to be zeroed (use calloc(3)), as well every time a value which
    needs init is changed.

    The init function must be REENTRANT: when called multiple times it
    should be aware of existing buffers and re-allocate them cleanly.

    @brief initialize filter instance according to its parameters
    @param livido_instance_t filter instance to (re)initialize
    @return error code
    */
typedef int (livido_init_f) (livido_instance_t*);

/**
   Free memory and cleanup internal variables.

   It must be called by host for de-initialization of filters when they
   are no more needed.

   @param livido_instance_t instance
   @return error code
*/
typedef int (livido_deinit_f) (livido_instance_t*);

/**
   Process input frames to output frames

   if plugin advertises the #LIVIDO_PROPERTY_CAN_DO_INPLACE flag, the
   output frames pointer may be NULL after execution.

   @param livido_instance_t correctly initialized plugin filter
   @param livido_frame_t input linked list of frame(s) to be processed
   @param livido_frame_t output linked list of frame(s) processed
   @return error code */
typedef int (livido_process_f) (livido_instance_t*,
				livido_frame_t*, livido_frame_t*);


/** ERROR CODES */

#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_instance::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

#define LIVIDO_ERROR_GET_PARAMETER              8
///< error occurred in get_parameter usage: wrong number of arguments or wrong format

#define LIVIDO_ERROR_SET_PARAMETER              9
///< error occurred in set_parameter usage: wrong number of arguments or wrong format

///@}












/////////////////////////////////////////////////////////////////
/**
   @defgroup parameter Parameters

   Livido Parameters are used by the plugin to describe the the
   controls of its filter, they should be parsed by the host and their
   values can be changed thru processing in order to change filter
   states.

   Parameters also include hints on how the user interface should
   offer interactivity to user.

   You can browse the ::livido_parameter_template struct to discover
   about which fields describe a parameter, while the
   ::livido_parameter struct holds the actual values for parameters.

   @{ */


// parameters data types
#define LIVIDO_PARAM_SWITCH             0x10  ///< on/off switch
#define LIVIDO_PARAM_NUMBER	        0x11  ///< double value
#define LIVIDO_PARAM_RGBA32	        0x13  ///< color triplet for RGBA (8 bits per channel)
#define LIVIDO_PARAM_RGB24	        0x14  ///< color triplet for RGB (8 bits per channel)
#define LIVIDO_PARAM_COORD2D	        0x15  ///< 2d cartesian coordinates (double)
#define LIVIDO_PARAM_STRING	        0x16  ///< string of maximum length = LIVIDO_STRING_SIZE
#define LIVIDO_PARAM_POINTER	        0x17  ///< pointer to custom data buffer
#define LIVIDO_PARAM_CUSTOM             0x18  ///< customized parameter (see scanf(3) description)




/** This flag should be declared by the plugin whenever it is strictly
    necessary to re-initialize the filter (i.e. to reallocate buffers)
    after the value of a certain parameter changes.

    GOOD PRACTICE: If possible, try avoiding use of this flag and
    write your plugin in a way that can handle dynamic changes of
    parameters while processing */
#define LIVIDO_PARAMETER_NEEDS_INIT (1<<0) ///< set by plugin: host needs to re-init parameter change

#define LIVIDO_PARAMETER_INTERPOLATED (1<<1) ///< set by host: plugin should interpolate value changes

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

   @brief template provided by the plugin to describe its public parameters
*/
struct livido_parameter_template {
  /** name should be short. lowercase. do not put in the words like
      "plugin" or "filter", but rather the name of the thing */
  const	char *name; ///< name of the parameter
  
  /** the description should explain what the parameter does, it can be multilined. */
  const	char *description; ///< description of the parameter
  
  const char *format; ///< parameter rendering description

  const	int type; ///< the parameter type (i.e #LIVIDO_PARAM_SWITCH)

  const	int flags; ///< flags of parameter (i.e #LIVIDO_PARAM_NEEDS_INIT)

  const int decimals; ///< how many decimals after the floating point

  const char *list_values; ///< multiple values list or NULL

  const char *def; ///< default value, rendered conforming to the format
  
  const double min; ///< minimum value for numerical parameters
  const double max; ///< maximum value for numerical parameters
  const double step; ///< step increment for value in numerical parameters


  /**
     hints are supposed to use some keyword system to describe the way
     a GUI should be rendered in order to modify the parameter, e.g:
     - layout|p1|fill|p2
     - special|aspect|1|2
     there will be a separate document about the hint system
     which is being implemented in the livido library */
  const char *hint;        ///< layout hints for the GUI renderer

  const void *extra; ///< for future expansion

  struct livido_parameter_template* next;
  ///< pointer to the next element in the list, NULL if end

  char reserved[64]; ///< reserved space for binary compatibility thru versions
};


/**
   This is the structure where parameters instances are allocated,
   holding the buffers of the actual values, information about
   interpolation of values.
   
   @brief instance allocated by the host from parameter templates, it holds actual values
*/
struct livido_parameter {

  struct livido_parameter_template *templ;
  ///< pointer to the template for this parameter

  char *value; ///< values rendered according to the scanf(3) definition

  int flags;   ///< parameter flags set by the host (i.e #LIVIDO_PARAM_INTERPOLATED)

  void *extra; ///< for extended use
  
  struct livido_parameter *next;
  ///< pointer to next parameter in list, NULL if end

  char reserved[64]; ///< reserved space for binary compatibility thru versions
};


/////////////////////////////////////////////////////////
/// PARAMETER FUNCTIONS

#include <stdio.h>
#include <stdarg.h>
#include <string.h>

/**
   This function can be used to set the values of instantiated
   parameters. Tt can be used both by the host and the plugin in order
   to communicate values to each other thru the processing cycle.
   
   For internal rendering it makes use of scanf/fprintf with the
   livido_parameter_template::format provided by the parameter
   template.

   The programmer using this function must clearly know in advance
   which parameter type is being set in order to supply the proper
   number of arguments: see livido_parameter_template::type

   @brief set parameter values in instance
   @param parameter reference to the instance of a parameter
   @param ... variable list of arguments, a la scanf(3)/fprintf(3)
   @returns 0 on success, #LIVIDO_ERROR_SET_PARAMETER on error
*/
int livido_set_parameter(livido_parameter_t *parameter, ...) {
  char tmp[1024];
  int len;
  va_list arg;
  int res;
  
  /// initialize parameter rendering format
  va_start(arg, parameter);
  
  /// render the parameter values
  res = vsnprintf(tmp, 1023, parameter->templ->format, arg);

  if(res<0) res = LIVIDO_ERROR_SET_PARAMETER;
  else {
    res = LIVIDO_NO_ERROR;
    if(parameter->value) free(parameter->value);

    len = strlen(tmp);
    parameter->value = calloc( len+1, sizeof(char) );
    strncpy(parameter->value, tmp, len);

  }

  va_end(arg);
  
  return res;
}

/**
   This function can be used to get the values of instantiated
   parameters inside variables of the proper type.

   It can be used both by the host and the plugin in order
   to communicate values to each other thru the processing cycle.

   For internal rendering it makes use of scanf/fprintf with the
   livido_parameter_template::format provided by the parameter
   template.

   The programmer using this function must clearly know in advance
   which parameter type is being read in order to supply the proper
   number and type of arguments: see livido_parameter_template::type
   
   @brief get parameter values in instance
   @param parameter reference to the instance of a parameter
   @param ... variable list of arguments (depending from livido_parameter_template::type)
   @returns 0 on success, LIVIDO_ERROR_SET_PARAMETER on error
*/
int livido_get_parameter(livido_parameter_t *parameter, ...) {
  va_list arg;
  const char *fmt;
  float *f;
  char *s;
  va_start(arg, parameter);

  /// render the parameter values
  fmt = parameter->templ->format;
  while (*fmt)
    switch(*fmt++) {
    case 's':           /* string */
      s = va_arg(arg, char *);
      sscanf(parameter->value, parameter->templ->format, s);
      //      fprintf(stderr,"get_parameter: string %s\n", s);
      break;
    case 'f':           /* int */
      f = va_arg(arg, float*);
      sscanf(parameter->value, parameter->templ->format, f);
      //      fprintf(stderr,"get_parameter: int %f\n", *f);
      break;
    }
  

  //  if(res == 0 || res == EOF) res = LIVIDO_ERROR_GET_PARAMETER;
  //  else res = LIVIDO_NO_ERROR;

  va_end(arg);

  return 0;
}



///@}





/////////////////////////////////////////////////////////////////
/**
   @defgroup filter_template Filter template

   The filter template is the filter abstraction provided by the
   plugin to describe itself and used by the host to create filter
   instances.
   
   A single plugin can provide multiple filter templates, therefore in
   Livido one plugin can provide different video effects.

   @{ */

/**
   The filter template structure contains informations as 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 channel templates describing the geometry of the video
   which the plugin will accept.
   
   @brief Template provided by the plugin to describe an effect
*/
struct livido_instance_template {

  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 flags;
  ///< non-exclusive flags describing filter properties (read-only)


  //////////////////////////////// parameter stuff /////////////////////


  /** CAVEAT: Never change the parameter order between different
      versions of plugin. This might annoy many hosts. */
  struct livido_parameter_template *in_parameter_templates;
  ///< linked list of parameter descriptions

  /** this pointer can be NULL if plugin does not support output parameters.

      CAVEAT: Never change the parameter order between different
      versions of plugin. This might annoy many hosts. */
  struct livido_parameter_template *out_parameter_templates;
  ///< linked list of parameter descriptions

  ////////////////////////////////////////////////////////////

  /** Host should use the lists of channel templates to create
     respective lists of channel instances (::livido_channel) inside
     the filter instance.

     The channels should keep the same order in both lists:
     correspondance between them is based on position.
  */

  struct livido_channel_template *in_channel_templates;
  ///< linked list of input channel templates

  struct livido_channel_template *out_channel_templates;
  ///< linked list of output channel templates


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

  char *hints; ///< hints about presenting of the plugin (GUI wise)

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

  struct livido_instance_template *next;
  ///< pointer to the next filter template in the list, NULL if end

  char reserved[64]; ///< reserved space for binary compatibility thru versions
};


/**
   The setup function must be called when the filter is loaded using
   dlopen(3) on the symbol "livido_setup", which returns a structure
   holding pointers to all filter templates provided by the filter.

   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_f()).

   It returns a variable length array of filter templates made
   available by the plugin.

   After calling the livido_setup(), an host application must call the
   initialization function contained in a filter template to obtain a
   filter from it.

   @brief Setup the global environment of the plugin.
   @return linked list of filter templates */
typedef struct livido_instance_template *(livido_setup_f) (void);


/*
  The flags that can be set in livido_instance_template::flags
  define aspects of the filter functioning, they are flags set by the
  plugin on the filter template, the host should always check them
  carefully (i.e: if(property&LIVIDO_PROPERTY_*)

*/

/**
   If this property is set, means that the filter can run in a (soft)
   realtime environment. The plugin must not do:

   - use malloc(3) free(3) 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
   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 LIVIDO_PROPERTY_CAN_DO_INPLACE (1<<0x1)
///< inplace filter propert

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

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

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

   The host must set the following properties in the filter in order
   to tell the plugin the geometry of the desired window:
   - livido_instance::window_x
   - livido_instance::window_y
   - livido_instance::window_w
   - livido_instance::window_h */
#define LIVIDO_PROPERTY_CAN_DO_WINDOWED (1<<0x4)
///< plugin is capable of doing window crop


#define LIVIDO_PROPERTY_SELF_AUTOMATION (1<<0x5)
///< plugin does automation by itself (keyframming)

/**
   The plugin absolutely needs frames_per_second information, don't
   try to use it without */
#define LIVIDO_PROPERTY_FPS_NEEDED (1<<0x6)
///< FPS information is mandatory

/**
   the effect ::livido_init_t should be called by host after it
   resizes any channel (and before it calls process)
*/
#define LIVIDO_PROPERTY_HOST_CAN_RESIZE (1<<0x7)
///< host can change channel sizes, should recall init() every time

/**
   the ::livido_init_t should be called by host after changing palette
   on any channel (and before it calls process)
*/
#define LIVIDO_PROPERTY_HOST_CAN_CHANGE_PALETTE (1<<0x8)
///< host can change palettes, should recall init() every time

/// @}
















/**
   @defgroup livido_channel_t Channel

   In Livido Channels describe the geometry of the frames given and
   returned. There can be variable amounts of input channels and
   output channels for each plugin filter (::livido_instance)

   Channels are passed in variable length arrays. By its position in
   the array each channel corresponds to a frame (::livido_frame)
   passed in the process plugin function (::livido_process).

   @{ */

/**

   A channel is an actual implementation of a channel template
   (::livido_channel_template) hold by the filter
   (::livido_instance) and setup by the host to prepare for
   initialization (::livido_init).

   If a channel template is optional (#LIVIDO_CHANNEL_OPTIONAL flag), the
   host can indicate whether is being used or not by setting the flag
   #LIVIDO_CHANNEL_DISABLED in this structure.

   @brief Instance of channel templates allocated and set by the host
   
*/
struct livido_channel {

  struct livido_channel_template *templ;
  ///< the template that this channel is based upon

  int flags; ///< flags that can be set by the host

  int palette;
  ///< the palette for the channel, from one of the palettes provided by the template

  int width; ///< channel width in pixels
  int height; ///< channel height in pixels

  int shift_h; ///< horizontal shift for planar YUV
  int shift_v; ///< vertical shift for planar YUV 

  /**
     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 and every plugin
     has to honour the rowstrides. */
  int rowstrides[4]; ///< length of one row in bytes (include padding)

  struct livido_channel *next;
  ///< pointer to the next channel in the list, NULL if end

  char reserved[64]; ///< reserved space for binary compatibility thru versions
};


#define LIVIDO_CHANNEL_DISABLED (1<<0)
///< flag set by host to tell plugin that this channel is deactivated


/// @}






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

   In Livido video frames are passed as structures. They hold the
   actual pixel data and link to geometrical informations about it.

   In case the corresponding channel is not resizable
   (#LIVIDO_CHANNEL_RESIZABLE is not set) the sizes of frames provided
   to the plugin may not change during processing: initialization must
   be called again on the filter.

   In case the corresponding channel is a mask (#LIVIDO_CHANNEL_MASK is
   set), the size of frames will vary due to the different size of
   components in masks, which is usually less than the actual frame
   palette, for instance in 1bit masks.

   @{ */




/**
   Livido only provides basic plugin awareness of time.

   This is given trough timecode parameter being passed during
   processing.

   At present Livido does not hold timecode for every specific
   channel, it is a general timing marking each call to the process
   function.

   The timecode 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)

*/

typedef double livido_timecode_t;

/**
   This structure stores the frame data along with informations on its
   geometry. It is passed along with frames to the process
   (::livido_process_f).
   
   @brief Struct holding pixel data to be used during processing

*/
struct livido_frame {

  void *pixel_data[4];         ///< pixel data is the array for planar modes
  
  struct livido_channel *channel;   ///< channel where interpretation of this data is available

  livido_timecode_t timecode;
  ///< timecode since 'play start' (RT) or start of the timeline (NLE)  

  void *extra;                 ///< extra pointer for data to pass along to the plugin

  char reserved[64]; ///< reserved space for binary compatibility thru versions
};

/// @}










/////////////////////////////////////////////////////////////////
/**
   @defgroup livido_instance_t Filter

   A filter is an allocated and initialized instance of a filter
   template.

   A blank filter structure is passed to the initialization function
   to be filled.

   The filter should be stored by the host and passed to the process
   function.

   At the end of its use, a filter should be free'd by the host which
   created it.

   @{ */

/**
   Function prototypes for memory handling wrappers */
typedef void *(livido_malloc_f)(size_t); ///< host provided malloc(3)
typedef void  (livido_free_f)(void*); ///< host provided free(3)
typedef void *(livido_memcpy_f)(void*, const void*, size_t); ///< host provided memcpy(3)
typedef void *(livido_memset_f)(void*, int, size_t); ///< host provided memset(3)

/**
   Function prototypes for keyframing: those are supplied by
   the host, passed thru the instance which gets initialized,
   in order to let the plugin call them during interpolation */
typedef int (get_keyframe_cb)(void *ctx, livido_instance_t *instance, livido_parameter_t *p,
			      livido_timecode_t pos, livido_timecode_t keyframe );



/**

   This struct is allocated at initialization of the plugin, setted up
   by the host accordingly to the template provided by the plugin,
   then passed to ::livido_init_f() for initialization.

   It should be allocated by the host, zeroed (use calloc(3)), setted
   up and free'd only by the host.
   It is important that the host remembers to call ::livido_deinit_f()
   before deallocating the memory.

   All variables inside the are read/write, so they should be set by
   the host application before initialization.

   The parameters array holds the real values for the parameters
   exposed by the filter, some of them require a new initialization.

   IMPORTANT: ALL parameters of filter structure are set by host with
   two exceptions:
   - internal (host never ever touch this, it is only for the plugin)
   - error set by plugin, #LIVIDO_NO_ERROR on success

   IMPORTANT: The list of parameters that the host can set after
   initialization:
   - fps
   - window_x, window_y, window_w, window_h
   - scale_x, scale_y
   But they must not be set during the call to process()!

   @brief Instance of an effect, allocated and set by the plugin, used in processing
*/

struct livido_instance {
  
  struct livido_instance_template *templ;
  ///< pointer to the filter template which spawned this filter


  struct livido_channel *in_channels; ///< array of IN channels for frame geometries

  struct livido_channel *out_channels; ///< array of OUT channels for frame geometries


  struct livido_parameter *in_parameters; ///< array of IN parameters
  
  struct livido_parameter *out_parameters; ///< array of OUT parameters


  get_keyframe_cb *keyframe_next; ///< function provided by host to get next keyframe

  get_keyframe_cb *keyframe_prev; ///< function provided by host to get previous keyframe

				 
  /**
     Set to 24 by default when using #LIVIDO_CREATE_FILTER), host
     should adjust it to desired frames per second. This value can be
     changed during processing */
  float fps; ///< frames per second desired by host (optional)

  /**
     If plugin can do scaled (#LIVIDO_PROPERTY_CAN_DO_SCALED flag is set)
     the following two values can be used and initialization must be
     called again on the current filter after every variation. */
  float scale_x; ///< horizontal scale multiplier
  float scale_y; ///< vertical scale multiplier

  /**
     The following four values should be used by the host if the plugin
     can do windowed (#LIVIDO_PROPERTY_CAN_DO_WINDOWED flag is set). */
  float window_x;  ///< horizontal coordinate of upper left corner
  float window_y; ///< vertical coordinate of upper left corner
  float window_w; ///< horizontal coordinate of lower right corner
  float window_h; ///< vertical coordinate of lower right corner

  /**
     Number of threads plugin should use if it can.
     1 by default, set it to higher numbers if you like to take
     advantage of multithreading in plugins supporting it. */
  int threads; ///< threads that the plugin is suggested to spawn by the host


  /** memory handling function pointers
      host can optionally provide the plugin with substitutes to the
      standard memory functions, plugin should use standard functions
      in case they are left NULL */
  livido_malloc_f *malloc; ///< memory allocation function, see malloc(3)
  livido_free_f   *free;   ///< memory free function, see free(3)
  livido_memcpy_f *memcpy; ///< memory copy function, see memcpy(3)
  livido_memset_f *memset; ///< memory set function, see memset(3)


  void *internal; ///< filter's private buffers, host can ignore this

  char *error; ///< error description, plugin sets this to const strings, NULL otherwise

  char reserved[64]; ///< reserved space for binary compatibility thru versions
};





/// @}





#endif // __LIVIDO_H__
