/*

NEW KMedia2 layout:
===================

KMedia1 itself doesn't play anything. Instead it has a backend for every
media type to play. It tells these backends: "start playing now", "stop
playing now" and similar things (using libmediatool). So there is a backend
for wave files, tacker files, midi files, etc., which all provide one
common interface.

The idea is to keep everything the old KMedia1 interface could do, but to
move to a new IPC architecture (MCOP).

That way, KMedia2 objects will be able to use the aRts streaming abilities.
Of course, not every KMedia2 object will need these, but some of them. The
result will be much nicer, if every of these objects can be treated in the
standard "flow graph" way, like other aRts objects can.

The ultimate media player, which KMedia2 aims to be, should play midi,
video, audio, etc. It is about seeing a file, choosing a component which
might be able to decode it, and play it. So it is not about starting
the right application, but about loading the right component.

This gives you the advantage that you can for instance reuse components
even between quite different media types. It may for instance make sense
to reuse a reverb effect to play midi, audio and video files.

*/

#include "artsflow.idl"

module Arts {

enum poState {
  posIdle,
  posPlaying,
  posPaused
};

// use 2^n values here, since they can (should) be or'd together
enum poCapabilities {
  capSeek = 1,
  capPause = 2
};

/**
 * KMedia2 time information
 *
 * This is a time value which contains either milliseconds & seconds, or
 * a custom unit or both. It is a flexible time base.
 *
 * If a value isn't there, it is set to -1.
 */
struct poTime {
	/**
	 * time it takes in seconds; -1 if no clock time known
	 */
    long seconds;

	/**
	 * additional time in milliseconds (this doesn't contain all the time)
	 * -1 if no clock time known
	 */
	long ms;

	/**
	 * some custom time information
	 * -1 if no custom time known
	 */
    float custom;

	/**
	 * for instance for a tracker "pattern"
	 */
    string customUnit;
};

/**
 * private part of the PlayObject API (don't use)
 */
interface PlayObject_private {
	/**
	 * loads a file
	 */
	boolean loadMedia(string filename);
};

/**
 * KMedia2 PlayObject - these can be used by Kaiman for instance
 */
interface PlayObject : PlayObject_private {
    readonly attribute string description;
    readonly attribute poTime currentTime;
    readonly attribute poTime overallTime;
    readonly attribute poCapabilities capabilities;
    readonly attribute string mediaName;
    readonly attribute poState state;

	/**
	 * starts playing the media
	 */
    void play();
	/**
	 * seeks to a specific time
	 */
    void seek(poTime newTime); // could be handled by setting currentTime
	/**
	 * pauses playing the media
	 */
    void pause();
	/**
	 * stop playing the media. Normally this function would called stop,
	 * but the name is reserved for the start/stop mechanism of the
	 * aRts objects.
	 */
    void halt();
};

/**
 * use this to create new PlayObjects for media
 */
interface PlayObjectFactory {
	/**
	 * creates a play object (or returns a null reference if this is not
	 * possible)
	 *
	 * @param filename the name of the file to create a play object for
	 */
	PlayObject createPlayObject(string filename);
};

/**
 * UNSTABLE/EXPERIMENTAL!
 */
interface InputStream : SynthModule {
	/**
	 * whether the stream is at the end of the input
	 */
	readonly attribute boolean eof;

	/**
	 * total size of the stream in bytes
	 *  -1: unknown
	 */
	readonly attribute long size;

	/**
	 * whether the stream can be seeked
	 */
	readonly attribute boolean seekOk;

	/**
	 * this returns the new AGE of the stream, where AGE is defined as the
	 * number of bytes that have been sent since the stream exists
	 */
	long seek(long position);

	/**
	 * the stream data
	 */
	async out byte stream outdata;
};

/**
 * UNSTABLE/EXPERIMENTAL! Example stream for files.
 */
interface FileInputStream : InputStream {
	attribute string filename;

	boolean open(string filename);
};

interface StdoutWriter : SynthModule {
	async in byte stream indata;
};

interface StreamPlayObject : PlayObject {
	/**
	 * prepares the playobject for the stream
	 */
	boolean streamMedia(InputStream instream);

	/**
	 * last used inputstream
	 * it should never change
	 */
	 InputStream inputStream();
};

/**
 * Playobject with adjustable speed
 */
interface PitchablePlayObject {
	/**
	 * speed relative to "original"/intended one
	 * (1.0=normal, 2.0=double ;-), 1.05=5% faster)
	 */
	attribute float speed;
};

/**
 * Extended Version of PlayObjectFactory
 */
interface PlayObjectFactoryV2 : PlayObjectFactory {
	/**
	 * creates a PlayObject
	 *
	 * @param url the url to create a play object for
	 * @param mimetype mimetype for the url
	 * @param createBUS specifies wheter to create the bus-uplink or not
	 */
	PlayObject createPlayObjectForURL(string url, string mimetype, boolean createBUS);

	/**
	 * creates a StreamPlayObject (used internally!)
	 *
	 * @param instream specifies the InputStream
	 * @param mimetype mimetype for the InputStream
	 * @param createBUS specifies wheter to create the bus-uplink or not
	 */
	PlayObject createPlayObjectForStream(InputStream instream, string mimetype, boolean createBUS);
};

};
