How Ecasound Queries LADSPA Plugin Ports

Ecasound queries the input, output, and control ports of a LADSPA (Linux Audio Developer's Simple Plugin API) plugin by dynamically loading the plugin's shared library and inspecting the standardized LADSPA_Descriptor structure. By parsing this descriptor, Ecasound reads the total port count, evaluates bitmask descriptors to classify whether each port is audio or control, determines data direction (input or output), and retrieves port names and value ranges to integrate the effect into its signal processing chain.

Shared Library Loading and Descriptor Access

Ecasound searches directories defined in the LADSPA_PATH environment variable to locate plugin shared object files (.so). When an effect is invoked, Ecasound uses the standard POSIX dynamic linking interface (dlopen()) to load the library into memory.

It then uses dlsym() to locate the mandatory entry-point function:

const LADSPA_Descriptor * ladspa_descriptor(unsigned long Index);

Ecasound calls ladspa_descriptor() starting at index 0 and increments the index until it encounters a NULL return pointer or locates the specific plugin requested by the user, matching either the plugin's unique integer ID or its case-sensitive Label string.

Reading Port Count and Port Descriptors

Once a matching LADSPA_Descriptor is located, Ecasound queries the plugin’s ports by reading the following structure members:

Ecasound iterates through the array from index 0 to PortCount - 1. For each index, it performs bitwise checks against the flags defined in ladspa.h to classify the port:

  1. Direction: It checks whether the port contains the LADSPA_PORT_INPUT or LADSPA_PORT_OUTPUT flag.
  2. Data Type: It checks whether the port contains the LADSPA_PORT_AUDIO or LADSPA_PORT_CONTROL flag.

By combining these flags, Ecasound classifies each port into one of four functional categories:

Querying Metadata and Parameter Hints

To present readable feedback to users and validate parameter limits, Ecasound evaluates two additional arrays in the descriptor:

Port Binding and Processing

After categorizing each port, Ecasound prepares the plugin for execution:

  1. It allocates float buffers for audio input and output streams.
  2. It assigns float storage for control inputs based on CLI arguments, controllers, or defaults.
  3. It calls the plugin's connect_port() function for each port index, passing a pointer to the corresponding memory location:
descriptor->connect_port(InstanceHandle, PortIndex, &DataLocation);

Whenever Ecasound processes an audio block, audio buffers and control values are read and written directly through these mapped memory addresses.