[linux-audio-dev] Re: A Plugin API

New Message Reply About this list Date view Thread view Subject view Author view Other groups

Subject: [linux-audio-dev] Re: A Plugin API
From: Paul Barton-Davis (pbd_AT_Op.Net)
Date: ma helmi  28 2000 - 12:12:46 EST


>systems in use at the moment. This is partly an attempt to provoke
>discussion but starting from something I'm pretty sure will work in its own
>right.

First, let me offer thanks for stepping up to the plate with a
concrete proposal. You have every right to be pissed off, as long as
you come up with stuff in response :)

I started off by writing a pretty response to this. I deleted it all,
and instead am trying to be more responsible by offering my own edited
version of your proposed API. Yes, its still kind of petty, but I may
as well get my coding style in where I can :) No offense intended,
hopefully none taken.

First, I still need to be a little petty :)

Lets drop the Microsoft "Hungarian" variable naming. Calling something
"iFoobar" because its currently an int means that if you ever change
the API so that the relevant thing is not an int, every use of iFoobar
has to be altered to fFoobar or whatever. 90% of more of those
alterations will be unnecessary.

OK, here is my revised version. I am still thinking about to fit
Csound opcodes into this scheme (non-trivial), but I would fairly
willing to undertake the use of this or a similar API into
Quasimodo. There were a few errors in your original header (mostly
using `&&' instead of `&').

Major changes: mostly just names, but:

      use of unsigned long for size quantities
      remove "const" - it is wrong to use it when the argument may
                       not be a const at all
      use typedef for float, so that a "double" version is easy to do.
      remove all mention of unit generators
      require 1:1 mapping from plugins to shared object files
      remove idea of descriptor accessor functions with a single
                       Well Known Named function in the shared object

--regards
--p

/* ladspa.h - Copyright 2000 Richard W.E. Furse & Paul Barton-Davis */

#ifndef LADSPA_INCLUDED
#define LADSPA_INCLUDED

/**********************************************************************/

/* Overview:

   There is a large number of synthesis packages in use or development
   on the Linux platform at this time. This API ('The Linux Audio
   Developer's Simple Plugin API') attempts to give programmers the
   ability to write simple plugins in C and link them
   dynamically ('plug') into a range of these packages ('hosts').
   It should be possible for any host and any plugin to
   communicate completely through this interface.

   This API is deliberately short and simple. To achieve compatibility
   with a range of promising Linux sound synthesis packages it
   attempts to find the 'lowest common denominator' in their logical
   behaviour. Having said this, certain limiting decisions are
   implicit, notably the use of a fixed type for all data transfer and
   absence of a parameterised 'initialisation' phase.

   Plugins are expected to use the 'control rate' thinking implicit in
   the Music N languages (including Csound). Plugins have 'ports' that
   are inputs or outputs for audio or control data and the plugin is
   `run' for a `block' corresponding to a short time interval measured
   in samples. Audio data is communicated using arrays of floats,
   allowing a block of audio to be processed by the plugin in a single
   pass. Control data is communicated using single LADSPA_Data
   values. Control data may only change once per call to the `run'
   function. It is not suitable for the transfer of many types of
   data, however this provides a significant performance benefit. The
   plugin may assume that all its inputs and outputs are bound before
   it is asked to run.

   This API contains very limited error-handling at this time.
*/

/* Fundamental data type passed around between plugins */

typedef float LADSPA_Data;

/*********************************************************************/

typedef int LADSPA_Properties;

/* Indicates that the plugin has a real-time dependency and so
   its output not be cached of subject to serious latency.
 */

#define LADSPA_PROPERTY_REALTIME 0x1

#define LADSPA_IS_REALTIME(x) ((x) & LADSPA_PROPERTY_REALTIME)

/***********************************************************************/

/* Unit Generator Ports:

   Plugins have 'ports' that are inputs or outputs of audio or
   data. Ports can communicate arrays of LADSPA_Datas (for audio-rate
   inputs/outputs) or single LADSPA_Datas (for control-rate
   input/outputs). This information is encapsulated in the
   LADSPA_PortDescriptor type which is assembled by ORing properties
   together. By default a port is an audio-rate output.
*/

typedef int LADSPA_PortDescriptor;

#define LADSPA_PORT_INPUT 0x1 /* port is for input */
#define LADSPA_PORT_OUTPUT 0x2 /* port is for output */
#define LADSPA_PORT_CONTROL 0x4 /* port is control-rate (single LADSPA_Data) */
#define LADSPA_PORT_AUDIO 0x8 /* port is audio-rate (LADSPA_Data array) */

#define LADSPA_IS_PORT_INPUT(x) ((x) & LADSPA_PORT_INPUT)
#define LADSPA_IS_PORT_OUTPUT(x) ((x) & LADSPA_PORT_OUTPUT)
#define LADSPA_IS_PORT_CONTROL(x) ((x) & LADSPA_PORT_CONTROL)
#define LADSPA_IS_PORT_AUDIO(x) ((x) & LADSPA_PORT_AUDIO)

/**********************************************************************/

/* Plugin Handles:

   This plugin handle indicates access to a particular
   instance of the plugin concerned. It is valid to compare
   this to NULL (0 for C++).
*/

typedef void * LADSPA_Handle;

/**********************************************************************/

/* Descriptor for a Type of Plugin:

   This structure is used to describe a type of plugin. It
   provides a number of functions to examine the type, instantiate it,
   link it to buffers and workspaces and to run it.
 */

struct LADSPA_Descriptor {

  /* This indicates a number of properties of the plugin. */

  LADSPA_Properties Properties;

  /* This member points to the name of the plugin
     (e.g. "Sine Oscillator").
   */

  const char * Name;

  /* This indicates the number of ports (input AND output) present on
     the plugin.
   */

  unsigned long PortCount;

  /* This member indicates an array of port descriptor. Valid indexes
     numbers vary from 0 to PortCount-1.
   */

  LADSPA_PortDescriptor * PortDescriptors;

  /* This member is a function pointer that takes a port number as an
     input and returns a short null-terminated string (e.g. "frequency
     (Hz)") describing the port. The string returned should be
     finished with (but not freed) before calling this method again in
     case the memory space is reused by the plugin.
   */

  const char * (*get_port_name)(unsigned long Port);

  /* This member is a function pointer that instantiates a plugin.
     A handle is returned, indicating the new function. The
     instantiation function accepts a sample rate as a
     parameter. Returns NULL if instantiation fails.
   */

  LADSPA_Handle (*instantiate)(unsigned long SampleRate);

  /* This member is a function pointer that connects a port on an
     instantiated plugin to a memory location at which a frame
     of data for the port will be read/written. The data location is
     expected to be an array of LADSPA_Data for audio rate ports or a single
     LADSPA_Data for control rate ports. Memory issues will be managed by
     the host. The plugin should read/write the data at these
     locations every frame and the data present at the time of this
     connection call should not be considered meaningful. Connection
     functions may be called more than once for a single instance of a
     plugin to allow the host to change the buffers that the unit
     generator is reading or writing. They must be called at least
     once for each port. When working with blocks of LADSPA_Datas, the unit
     generator should pay careful attention to the frame size passed
     to the run function as the block allocated may only just be large
     enough to contain the block of samples.
  */

   void (*connect_port)(LADSPA_Handle Instance,
                          unsigned long Port,
                        LADSPA_Data * DataLocation);

  /* This method is a function pointer that runs an instance of a unit
     generator for a frame. Two parameters are required: the first is
     a handle to the particular instance to be run and the second
     indicates the frame size (in samples) for which the unit
     generator may run.
  */

  void (*run)(LADSPA_Handle Instance,
              unsigned long sampleCount)

  /* Once an instance of a plugin has been finished with it
     can be deleted using the following function. The handle passed
     ceases to be valid after this call.
   */

  void (*cleanup)(LADSPA_Handle instance);

  /* Reserved area for extensions. Must be initialised to zero. */
  char reserved[1000];

};

/**********************************************************************/

/* Loading A Plugin:

   The exact mechanism by which a plugin is loaded is host-dependent,
   however all the host will need to know is the name of the
   shared object file containing the plugin.

   That is: plugins have a 1:1 mapping onto a shared object file.

*/

/**********************************************************************/

/* Writing a Plugin:

   A plugin programmer should include a function called
   "descriptor" with the following function prototype. This function
   should reside in the shared object corresponding to the plugin.
   
   A host will find the plugin shared object file by one means or
   another, and then lookup the "descriptor" function, call it,
   and proceed from there.

*/

typedef LADSPA_Descriptor * (*LADSPA_Descriptor_Function)(void);

/**********************************************************************/

#endif /* LADSPA_INCLUDED */

/* EOF */


New Message Reply About this list Date view Thread view Subject view Author view Other groups

This archive was generated by hypermail 2b28 : pe maalis 10 2000 - 07:23:27 EST