
/* LiViDO plugin example
 *
 * make it with:
 * $ gcc $CFLAGS -c plugin_example.c
 * $ ld -E -z now -shared plugin_example.o -o plugin_example.so
 *
 * Copyleft (C) 2004-2005 the Livido Architects
 *
 * This source code is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Public License as published
 * by the Free Software Foundation; either version 2 of the License,
 * or (at your option) any later version.
 *
 * This source code is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * Please refer to the GNU Public License for more details.
 *
 * You should have received a copy of the GNU Public License along with
 * this source code; if not, write to:
 * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * $Id: plugin_example.c 65 2005-04-18 16:08:19Z jaromil $
 *
 */

/** @file plugin_example.c

    @brief LiViDO plugin implementation example

 */


#include <livido.h>

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




//////////////////////////////////////////////////////////////
// DECLARE PUBLIC STRUCTURES OF PLUGIN

int plugin_example_palette[] = {
  LIVIDO_PALETTE_RGBAFLOAT,
  LIVIDO_PALETTE_RGB32,
  LIVIDO_PALETTE_END
};


livido_channel_template_t in_channel_template_input_1 = {
  .next = NULL,
  .name = "input 1",                  //< name of the channel
  .flags = 0,                         ///< flags fot this channel
  .palettes = plugin_example_palette, ///< list of palettes supported by plugin
  .same_as = 0, ///< size and palettes must be the same as another channel
  .width = 0,   ///< width 0 means the host can choose them arbitrarily
  .height = 0,  ///< height 0 means the host can choose them arbitrarily
  .next = NULL
};

livido_channel_template_t out_channel_template_output_1 = {
  .next = NULL,
  .name = "output 1", //< name of the channel
  .flags = (LIVIDO_CHANNEL_SAME_AS_SIZE | LIVIDO_CHANNEL_SAME_AS_PALETTE), ///< flags fot this channel
  .palettes = plugin_example_palette, ///< list of palettes supported by plugin
  .same_as = 1, ///< size and palettes must be the same as another channel
  .width = 0,   ///< width 0 means the host can choose them arbitrarily
  .height = 0,  ///< height 0 means the host can choose them arbitrarily
};


livido_parameter_template_t parameter_template_num1 = {
  .next = NULL,
  .name = "number", // short name
  .description =
  "This is an example parameter\n"
  "this description is also multiline", // description of the parameter
  .category = "example",
  .type = LIVIDO_PARAMETER_NUMBER,      // the parameter type
  .flags = 0, // flags
  .array = 1, // number of elements if array
  .def_num = 3.0 ,  // default value
  .min     = 1.0 ,  // minimum value
  .max     = 18.0,  // maximum value
  .step    = 0.1    // step increment
};

livido_parameter_template_t parameter_template_arr1 = {
  .next = &parameter_template_num1,
  .name = "color triplet",
  .description =
	  "This is an example numeric array parameter",
  .category = "rgb",
  .type = LIVIDO_PARAMETER_NUMBER,
  .flags = 0,
  .array = 3,
  .def_num = 0.0,
  .min = 0.0,
  .max = 256.0,
  .step = 1.0
};

livido_parameter_template_t parameter_template_str1 = {
  .next = &parameter_template_arr1,
  .name = "string",
  .description =
  "This is an example parameter\n"
  "it contains a string, but it could also be a list of strings",
  .category = "string",
  .type = LIVIDO_PARAMETER_STRING,
  .flags = 0,
  .def_str = "default string value"
};

livido_parameter_template_t parameter_template_strch1 = {
  .next = &parameter_template_str1,
  .name = "string choice",
  .description =
  "This is an example for a multiple choice of strings\n"
  "it is like a menu box with string choices",
  .category = "stringchoice",
  .type = LIVIDO_PARAMETER_STRING,
  .flags = 0,



  .def_str = "first|second|third|fourth|fifth",
  .max = 5.0,
  .def = { 
	  .str = "fri|sd",
	  .num = 2

  .def_num = 2
};

livido_parameter_template_t parameter_template_ptr1 = {
  .next = &parameter_template_strch1,
  .name = "memory pointer example",
  .description =
  "This is a memory pointer example"
  "a memory address is shared between host and plugin\n"
  "it can be an xpm image for instance, or sound",
  .category = "xpm",
  .type = LIVIDO_PARAMETER_MEMORY,
  .flags = 0,
  .def_ptr = 0x0
};
	

livido_instance_template_t effect_template_piksel = {
  .next = NULL,
  .name =   "livido example", // name of effect
  .author = "the livido architects", // author of effect
  .description =
  "this is the example plugin for livido\n"
  "it was started coding at the Piksel in the BEK", // long text description
  .version = 1, // effect version
  .livido_api_version = 1, // version of the livido api used
  .flags = (LIVIDO_PROPERTY_CAN_DO_INPLACE | LIVIDO_PROPERTY_REALTIME), // effect properties  
  .extra = NULL, ///< extra data pointer reserved for future use (void *)

  .out_channel_templates = &out_channel_template_output_1,
  .in_channel_templates = &in_channel_template_input_1,

  .out_parameter_templates = NULL,
  .in_parameter_templates = &parameter_template_ptr1
};



/* declare our init function */
int example_init(livido_instance_t *inst) {
  fprintf(stderr,"plugin example init called on instance %p\n",inst);

  inst->internal = NULL;
  /// @todo: check instance validity in plugin_example.c

  return 0; // success
}


int example_deinit(livido_instance_t *inst) {
  fprintf(stderr,"plugin example deinit called on instance %p\n",inst);

  if(inst->internal) free(inst->internal);

  return 0; // success
}


int example_process(livido_instance_t *effect,
		livido_frame_t *in, livido_frame_t *out) {

  livido_parameter_t *example_number, *example_array;
  livido_parameter_t *example_string, *example_memory;
  livido_parameter_t *example_stringchoice;

  fprintf(stderr,"plugin: process called on env=%p in=%p out=%p\n",
		  effect, in, out);

  // an example knows his own parameters: to make the code look cleaner
  // we can use descriptive names for variables holding them.
  example_number       = effect->in_parameters; // 1
  example_array        = effect->in_parameters->next; // 2
  example_string       = effect->in_parameters->next->next; // 3
  example_stringchoice = effect->in_parameters->next->next->next; // 4
  example_memory       = effect->in_parameters->next->next->next->next; // 5

  fprintf(stderr,"plugin: number parameter %.2f\n",example_number->num[0]);

  fprintf(stderr,"plugin: color  parameter %.0f %.0f %.0f\n",
		  example_array->num[0], example_array->num[1],
		  example_array->num[2]);

  fprintf(stderr,"plugin: string parameter \"%s\"\n",example_string->str);

  fprintf(stderr,"plugin: string choice: ");
  if(*example_stringchoice->num > example_stringchoice->templ->max) {
    fprintf(stderr,"out of bounds\n");
  } else {   // parse the selected value out of the list of strings,
    // make a local copy because strtok modifies the string
    int c;   // num is the selection, str the choices    
    char *tmp = strdup(example_stringchoice->str);
    char *s = strtok(tmp,"|");
    // advance the pointer to the selection
    for(c = 1; c < example_stringchoice->num[0] ; c++)
      s = strtok(NULL,"|");

    fprintf(stderr,"%s\n",s);
    free(tmp); // remember to free the local strtok copy
  }
  
  fprintf(stderr,"plugin: memory parameter %p\n",example_memory->ptr);

  return LIVIDO_NO_ERROR;
}


livido_instance_template_t *livido_setup() {

  // expose effect function pointers
  effect_template_piksel.init = example_init;
  effect_template_piksel.deinit = example_deinit;
  effect_template_piksel.process = example_process;

  // return template list to the host
  return &effect_template_piksel;
}
