/* CSL - Common Sound Layer
 * Copyright (C) 2000-2001 Stefan Westerfeld and Tim Janik
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General
 * Public License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, MA 02111-1307, USA.
 */
#include <artsflow.idl>

module CSL { // Common Sound Layer
  
/**
 * Direction of a stream
 */
enum Direction { dirInput, dirOutput };

/**
 * Format of a stream
 *
 *  - the formats are OR'd together in a "format construction kit"
 *  - the numbers are assigned in a way that you don't accidentially choose
 *    an undefined format by omitting a choice - just using 16 for instance
 *    would result in the error message
 *        * missing endianness
 *        * missing encoding
 *    and not in a "random" encoding/endianness being choosen
 */
enum StreamFormat {
/* EITHER: */
	/* choose one of these */
	sf_size_8						= 0x0008,
	sf_size_16						= 0x0010,
	sf_size_32						= 0x0020,

	sf_size_mask					= 0x00FF,

	/* choose one of these (not required for endian independant formats) */
	sf_endian_le 					= 0x0100,
	sf_endian_be 					= 0x0200,

	sf_endian_mask					= 0x0F00,

	/* choose one of these */
	sf_encoding_linear_signed 		= 0x1000,
	sf_encoding_linear_unsigned		= 0x2000,
	sf_encoding_float				= 0x3000,

	sf_encoding_mask				= 0xF000,

/* OR: */
	/* choose a predefined common format */
	sf_u8							= 0x2008,
	sf_s16_le						= 0x1110,
	sf_s16_be						= 0x1210,

	sf_float_le						= 0x3120,
	sf_float_be						= 0x3220
};

/**
 * StreamParameters
 */
struct StreamParams
{
	long rate;
	long channels;
	StreamFormat format;
};

struct StreamStatus
{
	long streamID;

	StreamParams streamParams;
	long streamBufferUsed;		/* used bytes of the stream buffer */
	long streamBufferSize;		/* size of the stream buffer */

	StreamParams artsParams;
	long artsBufferUsed;		/* used bytes in server <-> hardware buffer */
	long artsBufferSize;		/* size of the server <-> hardware buffer */
};

/**
 * CSL::Adapter - Adapter which plays and records CSL audio streams via
 * artsd. The idea of this interface is to limit communication to normal
 * function calls, as they can be easily implemented in C. The CSL Adapter
 * also hides reference counting from the client, by forwarding the functions
 * that PlayStream and RecordStream provide via it's own interface.
 */
interface Adapter {
	/**
	 * Creates a new stream in the given direction
	 */
	long open(string role, Direction dir);
    
	/**
	 * Modifies the parameters of a stream
	 *
	 * @returns true when the given parameters (especially the format) are
	 *          valid and supported, false otherwise
	 */
	boolean setParams(long streamID, StreamParams params);
    
    void setTitle(long streamID, string title);
    
	/**
	 * Closes a stream
	 */
	void close(long streamID);
    
	/**
	 * Writes bytes to a stream
	 */
	oneway void write(long streamID, sequence<byte> bytes);

	/**
	 * Reads bytes from a stream
	 */
	sequence<byte> read(long streamID, long len);

	/**
	 * Activates a stream (i.e. starts playing/recording data on it)
	 */
	void activate(long streamID);

	/**
	 * Suspends a stream (i.e. stops playing/recording data on it)
	 */
	void suspend(long streamID);

	/**
	 * Checks whether a stream is active
	 */
	boolean active(long streamID);

	/**
	 * Obtains the status for a stream
	 */
	StreamStatus status(long streamID);

/* OSS: sndctl_dsp_...
	- post:  tell driver that it is likely, that a pause in the output stream
	         is going to occur now

	- reset: reset stream, will discard any buffered bytes and reset the stream
	         to a state where it can accept new parameters

	- sync:  wait until the last byte of the stream has been played to the
	         device (is called implicitely on close)

mapped to:
	- post   => nothing (does this really make sense for us)?

	- reset  => clearBuffer(streamID);
				suspend(streamID);
	
	- sync  =>  waitPlayed(streamID);
*/

	/**
	 * clears all contents of the stream buffer
	 *
	 * note: for dOutput streams, you can't expect that silence will occur
	 *       immediately after the call of clearBuffer, as there might be
	 *       bytes already in the arts server buffer, which can't be unmixed
	 *       for dInput stream, similar thoughts are valid
	 */
	void clearBuffer(long streamID);

	/**
	 * waits until the stream buffer reaches a certain level
	 *
	 * for dInput streams, it waits until the stream buffer has _at least_
	 * the requested level, whereas for dOutput streams, it waits until the
	 * stream buffer has _at most_ the requested level (i.e. bufferUsed or
	 * less bytes are in the buffer)
	 *
	 * @returns the level that has been "really" reached - waitBufferLevel is
	 *          not guaranteed to return at the exact position the caller
	 *          requested it to return
	 */
	long waitBufferLevel(long streamID, long bufferUsed);

	/**
	 * waits until the last byte written to the stream has reached the speaker
	 *
	 * this is not equivalent to waitBufferLevel(streamID, 0), as the former
	 * only waits until the stream specific buffer is 0, but not until the
	 * data has propagated through the aRts buffer and really reached the
	 * speaker
	 *
	 * note: only works on dOutput streams
	 */
	void waitPlayed(long streamID);

	/**
	 * gets maps for a channel
	 * 
	 * <pre>
	 * #define CSL_PCM_CHANNEL_FRONT_LEFT	"<front-left>" (no const in mcopidl)
	 * #define CSL_PCM_CHANNEL_FRONT_RIGHT	"<front-right>"
	 * #define CSL_PCM_CHANNEL_CENTER		"<center>"
	 * #define CSL_PCM_CHANNEL_REAR_LEFT	"<rear-left>"
	 * #define CSL_PCM_CHANNEL_REAR_RIGHT	"<rear-right>"
	 * #define CSL_PCM_CHANNEL_SUB_WOOFER	"<sub-woofer>"
	 * </pre>
	 */
	sequence<string> channelMaps(long streamID);

	/**
	 * sets mapping for one channel
	 */
	boolean setChannelMapping(long streamID, long channel, string mapping);

	/**
	 * gets mapping for one channel
	 */
	string getChannelMapping(long streamID, long channel);

/* - stuff for samples - */
	long sampleNew(string name, string role, string title);
	void sampleRelease(long sampleID);

	oneway void sampleWrite(long sampleID, sequence<byte> bytes);
	void sampleWriteDone(long sampleID);

	/* playing samples */
	boolean samplePlay(long sampleID);
	boolean sampleIsPlaying(long sampleID);
	void sampleStop(long sampleID);
	void sampleWaitDone(long sampleID);

	/* sample cache */
	void sampleCacheAdd(long sampleID);
	long sampleCacheFind(string name, string role, string title);
	void sampleCacheRemove(long sampleID);
};

/**
 * - internal -
 *
 * used to implement CSL::Adapter, but not to be used directly
 */
interface Stream : Arts::SynthModule {
	readonly attribute long ID;
	readonly attribute Direction direction;

	readonly attribute string role;	/* = AudioManager autoRestoreID */
	attribute string title;			/* = AudioManager title */

	readonly attribute long bufferUsed;
	attribute long bufferSize;

	attribute StreamParams params;
	attribute boolean active;

	void clearBuffer();
	void close();
};

/**
 * - internal -
 *
 * used to implement CSL::Adapter, but not to be used directly
 */
interface PlayStream : Stream {
	oneway void write(sequence<byte> bytes);
	default out audio stream left, right;
};

/**
 * - internal -
 *
 * used to implement CSL::Adapter, but not to be used directly
 */
interface RecordStream : Stream {
	sequence<byte> read(long len);
	default in audio stream left, right;
};

/**
 * - internal -
 *
 * used to implement samples in CSL::Adapter
 */
interface PlaySample {
	readonly attribute long ID;
	attribute boolean finished;		// for Synth_PLAY_WAV callback
};

};
/****
 * Local Variables:
 * Mode:C
 * c-set-style:linux
 * indent-tabs-mode:nil
 * c-basic-offset:4
 * tab-width:4
 * End:
 */
