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 */
This archive was generated by hypermail 2b28 : pe maalis 10 2000 - 07:23:27 EST