aRts/MCOP heavily relies on splitting up things into small components. This makes things very flexible, as you can extend the system easily by adding new components, which implement new effects, fileformats, oscillators, gui elements, ... - as almost everything is a component, almost everything can be extended easily, without changing existing sources. New components can be simply loaded dynamically to enhance already existing applications.
However, to make this work, two things are required:
The combination of this: components which say "here I am, I am cool, use me", and applications (or if you like, other components) which go out and look which component they could use to get a thing done, is called trading.
In aRts, components describe themselves by specifying values that they "support" for properties. A typical property for a file-loading component could be the extension of the files that it can process. Typical values could be "wav", "aiff" or "mp3". In fact, every component may choose to offer many different values for one property. So one single component could offer reading both, "wav" and "aiff" files, by specifying that it supports these values for the property "Extension".
To do so, a component has to place a .mcopclass file at an appropriate place, containing the properties it supports, for our example, this could look like this (and would be installed in <componentdir>/Arts/WavPlayObject.mcopclass):
Interface=Arts::WavPlayObject,Arts::PlayObject,Arts::SynthModule,Arts::Object Author="Stefan Westerfeld <stefan@space.twc.de>" URL="http://www.arts-project.org" Extension=wav,aiff MimeType=audio/x-wav,audio/x-aiff
It is important that the filename of the .mcopclass-file also says what the interface of the component is called like. The trader doesn't look at the contents at all, if the file (like here) is called Arts/WavPlayObject.mcopclass, the component interface is called Arts::WavPlayObject (modules map to directories).
To look for components, there are two interfaces (which are defined in core.idl, so you have them in every application), called Arts::TraderQuery and Arts::TraderOffer. You to go on a "shopping tour" for components like this:
Arts::TraderQuery query;
query.supports("Interface","Arts::PlayObject"); query.supports("Extension","wav");
vector<Arts::TraderOffer> *offers = query.query();
vector<Arts::TraderOffer>::iterator i; for(i = offers->begin(); i != offers->end(); i++) cout << i->interfaceName() << endl; delete offers;
For this kind of trading service to be useful, it is important to somehow agree on what kinds of properties components should usually define. It is essential that more or less all components in a certain area use the same set of properties to describe themselves (and the same set of values where applicable), so that applications (or other components) will be able to find them.
property | type | use | description |
---|---|---|---|
Author | string | optional | This can be used to ultimately let the world know that you wrote something. You can write anything you like in here, e-mail adress is of course helpful. |
Buildable | boolean | recommended | This indicates whether the component is usable with RAD tools (such as Arts Builder) which use components by assigning properties and connecting ports. It is recommended to set this value to true for almost any signal processing component (such as filters, effects, oscillators, ...), and for all other things which can be used in RAD like fashion, but not for internal stuff like for instance Arts::InterfaceRepo. |
Extension | string | where relevant | Everything dealing with files should consider using this. You should put the lowercase version of the file extension without the "." here, so something like "wav" should be fine. |
Interface | string | required | This should include the full list of (useful) interfaces your components supports, probably including Arts::Object and if applicable Arts::SynthModule. |
Language | string | recommended | If you want your component to be dynamically loaded, you need to specify the language here. Currently, the only allowed value is "C++", which means the component was written using the normal C++ API. If you do so, you'll also need to set the "Library" property below. |
Library | string | where relevant | Components written in C++ can be dynamically loaded. To do so, you have to compile them into a dynamically loadable libtool (.la) module. Here, you can specify the name of the .la-File that contains your component. Remember to use REGISTER_IMPLEMENTATION (as always). |
MimeType | string | where relevant | Everything dealing with files should consider using this. You should put the lowercase version of the standard mimetype here, for instance "audio/x-wav". |
URL | string | optional | If you like to let people know where they can find a new version of the component (or a homepage or anything), you can do it here. This should be standard http or ftp URL. |