[linux-audio-dev] Plugin APIs (again)

David Olofson david at olofson.net
Thu Dec 12 18:27:01 UTC 2002


On Thursday 12 December 2002 22.26, Tim Hockin wrote:
[...]
> > > So why do we need Bays and Foos again, and not just
> > > ChannelDescriptors? Simpler is better ...
> >
> > Well, the problem with addressing Channels 1D is that Channels
> > move around if you change the number of Channels of a certain
> > kind. So, you're pretty much forced to reinstantiate the plugin
> > to change the Channel count.
>
> nono.  Plugin provides Channel Descriptors.  Host says
> newchannel_idx = plug->new_channel(channel_descriptor_idx);  The
> plugin does not re-order existing channels to group them together. 
> It gives an index to the host.  A 1-dimensional index.  The plugin
> just maps that index onto whatever it uses internally.

But the host is allowed to assume that it is in fact an *index*; not 
just a cookie?

Comparing this to Control Input cookies, the latter can be anything, 
and you *could* say they can have up to 32 dimensions theoretically. 
(The plugin can do whatever it wants with them.) Obiously, it's not 
recommended to ever think of these as indices anywhere outside the 
plugin that created them and understands them. :-)


[...]
> > 	* Is a *_channel_desc able to express whether it's an
> > 	  output or input?
>
> I had envisioned no.  I saw I/O channels as being ins and outs in
> one config (2ins 2outs, 1in 2out, etc) and ctrl_channels as the
> same.  Each XAP_control and XAP_descriptor flags whether it is
> in/out.  That could change.

I see. (No problem as long as there is no assumption that anything is 
both an input and an output and that kind of stuff.)


> > 	* What is the relation between control and I/O channels?
>
> Generally 1-1, though not mandatory.  The ONLY reason for
> seperating them is to allow interchangable IO on a control channel.
>  I'm not even sure that is needed.

How about a mixer with variable insert count? There are several ways 
to implement that, but I can't think of one that doesn't require 
either that dreaded "link" feature, or an extra level of "grouping"...


> > 	* How would you handle say, ctrl in + one audio in +
> > 	  two audio out?
>
> 1 Control Channel with an array of controls
> 1 IO Channel with 1 in and 2 outs
> The plugin has to indicate that they are compatible.
>
> if (plug->channel_compat(plug, ctrl_idx, io_idx)) {
> 	chan_id = plug->new_channel(plug, ctrl_idx, io_idx);
> 	...
> }

So, you basically have a bunch of control channel descriptions and a 
bunch of io channel descriptions, and then the host can test for 
valid combinations of those when adding new channels?


> Dig?

Interesting idea - but why restrict it to one ctrl and one io per 
channel?

What I'm thinking is, why not just have Port Templates, and then 
think of Channels as abstract objects to which you may attach various 
numbers of Port Sets (instance of Port Templates) of various kinds. 
Or mabybe we should use the term Bay for this concept?

/*
 * This struct describes a single type of Bay.
 * A Plugin may have any number of Bay Templates.
 * A Bay is an object that contains a 1D array of
 * Ports, all of the same type, and the Bay Template
 * defines the type of those Ports, as well as
 * min/max count and other info.
 */
struct XAP_bay_tmpl
{
	const char	*name;		/* Name of the Bay type */
	XAP_port_types	type;		/* Type of the Ports */
	int		min;		/* Minimum # of Ports */
	int		max;		/* Maximum # of Ports */
	const char	**labels;	/* Port labels (*) */
	XAP_control	*controls;	/* (ignored for Audio Ports) */
};

(*) Given that you can have Bays with variable Port counts, it might
    be a better idea to provide a call or something for hosts to get
    the Port labels after setting or changing the Port count. I'm
    thinking in terms of 1 Port ==> "mono" vs 2 Ports ==> "left",
    "right".

I don't like the last field, but rather that than different kinds of 
templates... I think. Maybe there are better ways. Expressing the 
whole Bay Template as a string could work... I think I like that idea.

Either way, next; there are two approaches, simple...

/*
 * This describes a single type of Channel.
 * A Plugin may have any number of Channel Templates.
 * A Channel Template defines one valid combination
 * of Bays that can form one Channel instance.
 * A Channel may contain any number of Bays.
 * Bays are not optional, and each entry in the
 * Channel template corresponds to exactly one Bay
 * in a Channel instance.
 */
struct XAP_channel_tmpl
{
	const char	*name;		/* Name of this type of channel */
	int		nbays;		/* Number of Bays */
	const char	**labels;	/* Bay labels */
	XAP_bay_tmpl	**templates;	/* The Bay Templates */
};


...or a bit more flexible...

/*
 * This struct forms one entry in the list of
 * Bay Templates referenced by a Channel Template.
 * The Bay Strip describes a 1D array of identical
 * Bays. If min < max, the Bay count in the Strip
 * is variable.
 */
struct XAP_bay_strip
{
	const char	*name;		/* Name of this array of Bays */
	int		min;		/* Minimum # of Bays of this kind */
	int		max;		/* Maximum # of Bays of this kind */
	const char	**labels;	/* Labels for the Bays */
	XAP_bay_tmpl	*template;	/* The Bay Template */
};

/*
 * This describes a single type of Channel.
 * A Plugin may have any number of Channel Templates.
 * A Channel Template defines one or more valid
 * combinations of Bays that can form one Channel.
 * A Channel may contain any number of Bays.
 */
struct XAP_channel_tmpl
{
	const char	*name;		/* Name of this Channel type */
	int		min;		/* Min # of channels of this kind */
	int		max;		/* Max # of channels of this kind */
	int		nstrips;	/* Number of strips */
	const char	**labels;	/* Names for the strips */
	XAP_bay_strip	**strips;	/* The Bay Strips of this Channel type */
};

(Note that there are some inconsistencies WRT what min/max and 
labels/names apply to. That's confusing and must be dealt with.)


Now, one way or another, the Host gets a bunch of XAP_channel_tmpl 
structs, and then it can start asking for instances of those. 


> This allows us to have IO Channels be interchangeable, including
> data format, if we REALLY want.  Alternatively, we could just have
> some method of changing any port (if it supports it) to/from
> INT/FLOAT.

That sounds pretty cool. I'm not sure I'm seeing the full picture 
yet, though; I'll have to thing some about it.


> The simples answer of all, and the one I don't mind is just to have
> one big ChannelDesc that identifies the controls, the ins and the
> outs all together. No compat matrix, no mis-matches.

Yeah. The only problem with that is that you can't have multiple 
"groups" of Ports of the same type in a ChannelDesc. There is only 
room for one group of control inputs, one group of audio inputs etc. 
My proposal above is essentially the same structure, but makes the 
ChannelDesc dynamic, so you don't have to add extra ChannelDescs for 
extra Ports.

For example, the audio ins and outs of a mixer strip would be for the 
input and bus sends. Where would you fit the inserts? How would you 
support variable numbers of inserts?


//David Olofson - Programmer, Composer, Open Source Advocate

.- The Return of Audiality! --------------------------------.
| Free/Open Source Audio Engine for use in Games or Studio. |
| RT and off-line synth. Scripting. Sample accurate timing. |
`---------------------------> http://olofson.net/audiality -'
.- M A I A -------------------------------------------------.
|    The Multimedia Application Integration Architecture    |
`----------------------------> http://www.linuxdj.com/maia -'
   --- http://olofson.net --- http://www.reologica.se ---



More information about the Linux-audio-dev mailing list