    /*

    Copyright (C) 2000 Stefan Westerfeld
                       stefan@space.twc.de

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.
  
    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.

    */

/*
 * arts.idl - MCOP port. What's missing currently in MCOP?
 *
 * -   namespaces (module)
 */

module Arts {  // analog real time synthesizer

enum AutoSuspendState { asNoSuspend, asSuspend, asSuspendStop };

/**
 * The SynthModule interface is the base for all modules containing streams.
 *
 * There are two goals achieved by this interface. On one side, there is
 * functionality which users of stream carrying modules want to use (which
 * is: start streaming, stop streaming).
 *
 * On the other hand, there is functionality which the flow system will use
 * to achieve these goals.
 */
interface SynthModule {
	// interface for users of this module

	/**
	 * This function starts the streaming (e.g. the module will start
	 * producing samples) - if you write a module, do not reimplement this,
	 * instead reimplement streamInit/streamStart
	 */
	void start();

	/**
	 * This function stops the streaming - if you write a plugin, do not
	 * reimplement this, instead reimplement streamEnd
	 */
	void stop();

	// interface for people implementing modules

	/**
	 * this is supposed to be the initialization every module passes after
	 * all attributes have been set up (e.g. you can see which file to open,
	 * how to initialize your filter coefficients or whatever)
	 */
	void streamInit();

	/**
	 * starts the I/O of the module
	 */
	void streamStart();

	/**
	 * stop the thing again, and free data possibly allocated in streamInit
	 */
	void streamEnd();

	/**
	 * If you run a mixer desk (without anything connected), no calculations
	 * need to be done - since the output is silent anyway. For this reason,
	 * there exists this autosuspend attribute. It allows the flow system
	 * to detect the idle condition, and start suspending the calculations,
	 * until something "important" happens again.
	 *
	 * There are three possible values:
	 *
	 * @li  asNoSuspend - this one is appropriate when you have a module that
	 *                    is active by itself
	 * @li  asSuspend   - this one is appropriate for modules that "do nothing"
	 *                    by themselves
	 * @li  asSuspendStop - this one is for modules that should be stopped, when
	 *                    the system gets suspended, and restarted when the
	 *                    system will start again - an example for this is
	 *                    soundcard output
	 *
	 * A module should choose asSuspend (or asSuspendStop) only if the
	 * following conditions are true:
	 *
	 * @li given constant inputs (like 3.0 on all ports), the module will
	 *     give constant output after some time
	 * @li given only 0.0 inputs, the module will give only 0.0 outputs
	 *     after some time
	 * @li the module does not synchronize itself through signal flow (i.e.
	 *     a midi sequence which "knows" when a second has passed through
	 *     the signal flow breaks when suspension happens)
	 * @li the module can't be brought to do something with a method
	 *     invocation (i.e. a module which starts generating noise for
	 *     a second whenever the noise() method is called is not suspendable)
	 * @li the module has no internal state that changes over time when only
	 *     constant inputs are given
	 *
	 * Typical examples for suspendable modules are arithmetic operations,
	 * filters, delay/hall/reverb, soundcard output.
	 *
	 * Typical examples for non-suspendable modules are sequences, midi stuff,
	 * soundcard input (isn't constant even when nothing else happens),
	 * oscillators, sample players,...
	 */
	readonly attribute AutoSuspendState autoSuspend;
};

/**
 * Plays a stream of audio data to the soundcard
 */
interface Synth_PLAY : SynthModule {
	// attribute string channels;
	default in audio stream invalue_left,invalue_right;
};

/**
 * Records a stream of audio data from the soundcard
 */
interface Synth_RECORD : SynthModule {
	// attribute string channels;
	default out audio stream left,right;
};

/**
 * A frequency generator
 *
 * This kind of object is used to create frequencies. Oscillators are connected
 * at the output of this object
 */
interface Synth_FREQUENCY : SynthModule {
	in audio stream frequency;
	out audio stream pos;
};

/**
 * A sine wave
 */
interface Synth_WAVE_SIN : SynthModule {
	in audio stream pos;
	out audio stream outvalue;
};

/**
 * A module which mixes an arbitary number of audio streams
 */
interface Synth_MULTI_ADD : SynthModule {
	in multi audio stream invalue;
	out audio stream outvalue;
};

/**
 * A module which adds two audio streams
 */
interface Synth_ADD : SynthModule {
	default in audio stream invalue1,invalue2;
	out audio stream outvalue;
};

/**
 * Multiplies two audio streams
 */
interface Synth_MUL : SynthModule {
	in audio stream invalue1,invalue2;
	out audio stream outvalue;
	default invalue1, invalue2;
};

/**
 * This plays a wave file
 */
interface Synth_PLAY_WAV : SynthModule {
	/**
	 * How fast should it be played? 1.0 = normal speed
	 */
	attribute float speed;
	/**
	 * Which file should be played
	 */
	attribute string filename;
	/**
	 * Is true as soon as the file is finished
	 */
	readonly attribute boolean finished;

	out audio stream left, right;
	default left, right;
};

/**
 * sends data to a bus - busses are dynamic N:M connections - all signals
 * from all uplinks are mixed together, and sent to all downlinks
 */
interface Synth_BUS_UPLINK : SynthModule {
	/**
	 * the name of the bus to use
	 */
	attribute string busname;

	default in audio stream left,right;
};

/**
 * receives data from a bus - busses are dynamic N:M connections - all signals
 * from all uplinks are mixed together, and sent to all downlinks
 */
interface Synth_BUS_DOWNLINK : SynthModule {
	/**
	 * the name of the bus to use
	 */
	attribute string busname;

	default out audio stream left,right;
};


/**
 * Byte stream to audio conversion object
 *
 * Converts an asynchronous byte stream to a synchronous audio stream
 */
interface ByteStreamToAudio : SynthModule {
	attribute long samplingRate;
	attribute long channels;
	attribute long bits;

	/**
	 * is conversion currently running, or is it stalled due to the fact
	 * that there is not enough input input?
	 */
	readonly attribute boolean running;

	async in byte stream indata;

	out audio stream left,right;
	default left;
	default right;
};

/**
 * Base interface for all stereo effects
 */
interface StereoEffect : SynthModule {
	default in audio stream inleft, inright;
	default out audio stream outleft, outright;
};

/**
 * this is a simple clipping stereo volume control
 */
interface StereoVolumeControl : StereoEffect {
	attribute float scaleFactor;
	readonly attribute float currentVolumeLeft;
	readonly attribute float currentVolumeRight;
};

/**
 * A funny FFT scope
 */
interface StereoFFTScope : StereoEffect {
	readonly attribute sequence<float> scope;
};

/**
 * A stack of stereo effects
 */
interface StereoEffectStack : StereoEffect {
	/**
	 * inserts an effect at the top side (= directly after the input)
	 *
	 * @returns an ID which can be used to remove the effect again
	 */
	long insertTop(StereoEffect effect, string name);

	/**
	 * inserts an effect at the bottom (= close to the output) side
	 *
	 * @returns an ID which can be used to remove the effect again
	 */
	long insertBottom(StereoEffect effect, string name);

	/**
	 * removes an effect again
	 */
	void remove(long ID);
};

/*
 * Audio Manager stuff
 */

enum AudioManagerDirection { amPlay, amRecord };

/**
 * Information structure for audio manager clients
 */
struct AudioManagerInfo {
	long ID;
	string destination;

	AudioManagerDirection direction;
	string title, autoRestoreID;
};

/**
 * an audio manager client
 */
interface AudioManagerClient {
	readonly attribute long ID;
	attribute AudioManagerDirection direction;
	attribute string title, autoRestoreID;

	void constructor(AudioManagerDirection direction, string title,
					 string autoRestoreID);
};

/**
 * The audio manager interface
 */
interface AudioManager {
	/**
	 * a list of destinations, where you can play/record data to/from
	 */
	readonly attribute sequence<string> destinations;

	/**
	 * a list of clients
	 */
	readonly attribute sequence<AudioManagerInfo> clients;

	/**
	 * this is incremented each time a change is made (i.e. new client attached)
	 * TODO: SHOULD GO AWAY WITH ATTRIBUTE WATCHING
	 */
	readonly attribute long changes;

	/**
	 * this is used to route a client to another destination
	 */
	void setDestination(long ID, string destination);
};
/**
 * This is a virtual output port, which you use to play data. Where exactly
 * this data gets played is managed by the audiomanager.
 *
 * Creation: there are two ways to initialize a Synth_AMAN_PLAY - one is
 * to set title and autoRestoreID to sensible (non empty) values. The other
 * is to pass an already initialized AudioManagerClient on the constructor.
 */
interface Synth_AMAN_PLAY : SynthModule {
	attribute string title, autoRestoreID;
	void constructor(AudioManagerClient client);

	default in audio stream left, right;
};

/**
 * This is a virtual input port, which you use to record data. Where this
 * data comes from is in turn managed by the audiomanager.
 *
 * Creation: there are two ways to initialize a Synth_AMAN_RECORD - one is
 * to set title and autoRestoreID to sensible (non empty) values. The other
 * is to pass an already initialized AudioManagerClient on the constructor.
 */
interface Synth_AMAN_RECORD : SynthModule {
	attribute string title, autoRestoreID;
	void constructor(AudioManagerClient client);

	default out audio stream left, right;
};


};
