/*
 * AXEL -- An audio mixing and sequencing library.
 *
 * Copyright (C) 2001 Commonwealth Scientific and Industrial Research
 * Organisation (CSIRO), Australia.
 *
 * 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
 *
 */

/*
 * axel.h -- Base types and public interfaces to AXEL
 *
 * Conrad Parker <Conrad.Parker@CSIRO.AU>, August 2001
 */

#ifndef __AXEL_H__
#define __AXEL_H__

#include "ctxdata.h"

#define AxNone NULL

typedef int AxError;

typedef float AxPCM;

typedef long AxCount;
#define AX_COUNT_MAX (LONG_MAX - 1L)
#define AX_COUNT_MIN LONG_MIN
#define AX_COUNT_INFINITE AX_COUNT_MAX

typedef void * AxOpaque;

#if defined (__AXEL__)
typedef struct _AxBase * AxBase;
#else
typedef AxOpaque AxBase;
#endif

typedef CDScalar AxParameter;

typedef int AxFlags;
typedef double AxSamplerate;
typedef double AxTempo;
typedef union _AxTime AxTime;


/* Errors */
#define AX_ERROR_OK              0
#define AX_ERROR_INVALID         1
#define AX_ERROR_NOENTITY        2
#define AX_ERROR_EXISTS          3
#define AX_ERROR_SILENCE         4
#define AX_ERROR_NOOP            5
#define AX_ERROR_SYSTEM          6

typedef enum {
  AX_CHANNEL_LEFT,
  AX_CHANNEL_RIGHT,
  AX_CHANNEL_CENTRE,
  AX_CHANNEL_REAR,
  AX_CHANNEL_REAR_LEFT,
  AX_CHANNEL_REAR_RIGHT,
  AX_CHANNEL_REAR_CENTRE,
  AX_CHANNEL_LFE /* Low Frequency Effects */,
} AxChannelName;

typedef enum {
  AX_TIME_INVALID,
  AX_TIME_SAMPLES,
  AX_TIME_SECONDS,
  AX_TIME_BEAT24S
} AxTimeType;

/* Envelope types */
typedef enum {
  AX_ENVELOPE_LINEAR,
  AX_ENVELOPE_SPLINE
} AxEnvelopeType;

union _AxTime {
  long TIME;
  AxCount samples;
  float seconds;
  int beat24s;
};

typedef enum {
  AX_TYPE_BOOL = 0,
  AX_TYPE_INT,
  AX_TYPE_FLOAT,
  AX_TYPE_STRING,
  AX_TYPE_BASE,
} AxParameterType;

typedef enum {
  AX_CONSTRAINT_TYPE_NONE = 0,
  AX_CONSTRAINT_TYPE_LIST,
  AX_CONSTRAINT_TYPE_RANGE,
} AxConstraintType;


#define AX_RANGE_LOWER_BOUND_VALID (1<<0)
#define AX_RANGE_UPPER_BOUND_VALID (1<<1)
#define AX_RANGE_STEP_VALID        (1<<2)
#define AX_RANGE_ALL_VALID (AX_RANGE_LOWER_BOUND_VALID | \
                            AX_RANGE_UPPER_BOUND_VALID | \
                            AX_RANGE_STEP_VALID)

#define AX_HINT_DEFAULT  (0)
#define AX_HINT_LOG      (1<<0)
#define AX_HINT_TIME     (1<<1)
#define AX_HINT_FILENAME (1<<2)

#define AX_CONSTRAINT_EMPTY ((AxConstraint){NULL})

#define AX_SAMPLES(x) ((AxTime){(AxCount)(x)})
#define AX_SECONDS(x) ((AxTime){(float)(x)})
#define AX_BEAT24S(x) ((AxTime){(int)(x)})


#if (defined(__AXEL__) || defined(__AXEL_PLUGIN__))
#include <axel_plugin.h>
#else
typedef AxOpaque AXEL;
typedef AxOpaque AxPoint;
typedef AxOpaque AxEnvelope;
typedef AxOpaque AxChunk;
typedef AxOpaque AxChannel;
typedef AxOpaque AxStream;
typedef AxOpaque AxDeck;
typedef AxOpaque AxTrack;
typedef AxOpaque AxLayer;
typedef AxOpaque AxSound;
typedef AxOpaque AxMetaAuthor;
typedef AxOpaque AxMetaText;
typedef AxOpaque AxPlugin;
typedef AxOpaque AxSquareTone;
typedef AxOpaque AxMonitor;
#endif


#if defined(__cplusplus)
extern "C" {
#endif

extern CDSet AX_MONO;
extern CDSet AX_STEREO;


/* AXEL */
AXEL axel_init (void);
AXEL axel_init_clone (AXEL axel);
void axel_purge (AXEL axel);
AxError ax_last_error (AXEL axel);
char * ax_error_string (AXEL, AxError error);
AxSamplerate ax_set_samplerate (AXEL axel, AxSamplerate samplerate);
AxSamplerate ax_get_samplerate (AXEL axel);
AxTempo ax_set_tempo (AXEL axel, AxTempo tempo);
AxTempo ax_get_tempo (AXEL axel);
CDSet ax_set_channels (AXEL axel, CDSet channelset);
CDSet ax_get_channels (AXEL axel);

#if 0
  /* XXX */
/* Sources: Plugins, Samples etc. */
CDList ax_open (AXEL axel, char * filename);
void ax_close (AXEL axel, AxPlugin plugin);
#endif

/* Base objects */

AxPlugin ax_find_plugin (AXEL axel, char * identifier);

AxBase ax_new (AXEL axel, AxPlugin plugin, CDSet parameters);
CDSet ax_suggest (AXEL axel, AxPlugin plugin, CDSet parameters);

int ax_get_init_parameter_key (AXEL axel, AxPlugin plugin, char * name);
int ax_get_parameter_key (AXEL axel, AxBase base, char * name);

AxParameter ax_set_parameter (AXEL axel, AxBase base, int key,
			      AxParameter parameter);
AxParameter ax_get_parameter (AXEL axel, AxBase base, int key);
AxParameterType ax_get_parameter_type (AXEL axel, AxBase base, int key);


AxBase ax_clone_subclass (AXEL axel, AxBase base);
int ax_destroy (AXEL axel, AxBase base);
int ax_destroy_list (AXEL axel, CDList list);
AxBase ax_prepare (AXEL axel, AxBase base);
AxCount ax_process (AXEL axel, AxBase base, AxCount count, AxStream input,
		    AxStream output);
AxCount ax_length (AXEL axel, AxBase base);
AxCount ax_seek (AXEL axel, AxBase base, AxCount offset, int whence);
AxCount ax_tell (AXEL axel, AxBase base);
int ax_flush (AXEL axel, AxBase base);


/* Decks */
AxDeck ax_deck_new (AXEL axel);

AxCount ax_deck_set_mixlength (AXEL axel, AxDeck deck, AxCount mixlength);
AxCount ax_deck_get_mixlength (AXEL axel, AxDeck deck);

CDList ax_deck_get_tracks (AXEL axel, AxDeck deck);

/* Tracks */
AxTrack ax_add_track (AXEL axel, AxDeck deck);
AxPCM ax_track_set_gain (AXEL axel, AxTrack track, AxPCM gain);
AxPCM ax_track_get_gain (AXEL axel, AxTrack track);
AxCount ax_track_set_mixlength (AXEL axel, AxTrack track, AxCount mixlength);
AxCount ax_track_get_mixlength (AXEL axel, AxTrack track);
void ax_remove_track (AXEL axel, AxTrack track);

AxDeck ax_track_get_deck (AXEL axel, AxTrack track);


/* Layers */
AxLayer ax_add_layer_ontop (AXEL axel, AxTrack track, AxTimeType timetype);
AxLayer ax_add_layer_above (AXEL axel, AxLayer above, AxTimeType timetype);
AxLayer ax_move_layer_ontop (AXEL axel, AxLayer layer, AxTrack track);
AxLayer ax_move_layer_above (AXEL axel, AxLayer layer, AxLayer above);
AxLayer ax_raise_layer (AXEL axel, AxLayer layer);
AxLayer ax_lower_layer (AXEL axel, AxLayer layer);
AxTrack ax_layer_get_track (AXEL axel, AxLayer layer);
AxDeck ax_layer_get_deck (AXEL axel, AxLayer layer);
AxTimeType ax_layer_set_timetype (AXEL axel, AxLayer layer,
				  AxTimeType new_type);
AxTimeType ax_layer_get_timetype (AXEL axel, AxLayer layer);
AxSound ax_layer_get_sound_before (AXEL axel, AxLayer layer, AxTime time);
AxSound ax_layer_get_sound_at (AXEL axel, AxLayer layer, AxTime time);
AxSound ax_layer_get_sound_after (AXEL axel, AxLayer layer, AxTime time);
AxLayer ax_get_layer_below (AXEL axel, AxLayer layer);
AxLayer ax_get_layer_above (AXEL axel, AxLayer layer);

/* Sounds */
AxSound ax_add_sound (AXEL axel, AxBase source, AxLayer layer,
		      AxTime start_time, AxTime duration);
AxSound ax_remove_sound (AXEL axel, AxSound sound);

AxBase ax_sound_set_source (AXEL axel, AxSound sound, AxBase source);
AxBase ax_sound_get_source (AXEL axel, AxSound sound);
AxLayer ax_sound_get_layer (AXEL axel, AxSound sound);
AxTrack ax_sound_get_track (AXEL axel, AxSound sound);
AxDeck ax_sound_get_deck (AXEL axel, AxSound sound);

AxTime ax_sound_move (AXEL axel, AxSound sound, AxTime time);
AxSound ax_sound_get_prev (AXEL axel, AxSound sound);
AxSound ax_sound_get_next (AXEL axel, AxSound sound);

AxTime ax_sound_set_start_time (AXEL axel, AxSound sound, AxTime time);
AxTime ax_sound_get_start_time (AXEL axel, AxSound sound);
AxTime ax_sound_set_duration (AXEL axel, AxSound sound, AxTime time);
AxTime ax_sound_get_duration (AXEL axel, AxSound sound);

AxBase ax_sound_set_rate_envelope (AXEL axel, AxSound sound,
				   AxBase rate_envelope);
AxBase ax_sound_get_rate_envelope (AXEL axel, AxSound sound);
AxBase ax_sound_set_gain_envelope (AXEL axel, AxSound sound,
				   AxBase gain_envelope);
AxBase ax_sound_get_gain_envelope (AXEL axel, AxSound sound);
AxBase ax_sound_set_blend_envelope (AXEL axel, AxSound sound,
				    AxBase blend_envelope);
AxBase ax_sound_get_blend_envelope (AXEL axel, AxSound sound);


/* Envelopes */
AxEnvelope ax_envelope_new (AXEL axel, AxEnvelopeType type);
AxEnvelopeType ax_envelope_set_type (AXEL axel, AxEnvelope envelope,
				     AxEnvelopeType type);
AxEnvelopeType ax_envelope_get_type (AXEL axel, AxEnvelope envelope);
AxTimeType ax_envelope_set_timetype (AXEL axel, AxEnvelope envelope,
				     AxTimeType timetype);
AxTimeType ax_envelope_get_timetype (AXEL axel, AxEnvelope envelope);
AxPCM ax_envelope_get_value (AXEL axel, AxEnvelope envelope, AxTime time);
AxTime ax_envelope_get_duration (AXEL axel, AxEnvelope envelope);
AxPCM ax_envelope_get_integral (AXEL axel, AxEnvelope envelope,
				AxTime t1, AxTime t2);
AxPoint ax_envelope_add_point (AXEL axel, AxEnvelope envelope, AxTime time,
			       AxPCM value);
AxEnvelope ax_envelope_remove_point (AXEL axel, AxEnvelope envelope,
				     AxPoint point);
AxEnvelope ax_envelope_scale (AXEL axel, AxEnvelope envelope, AxPCM gain);
AxEnvelope ax_envelope_shift (AXEL axel, AxEnvelope envelope, AxTime delta);


/* Streams */
AxStream ax_stream_new (AXEL axel);
AxStream ax_stream_new_contiguous (AXEL axel, AxCount length);
AxCount ax_stream_nr_channels (AXEL axel, AxStream stream);
AxChannel ax_stream_find_channel (AXEL axel, AxStream stream, int name);
AxChannel ax_stream_add_channel (AXEL axel, AxStream stream, int name);
AxStream ax_stream_remove_channel (AXEL axel, AxStream stream, int name);
AxStream ax_stream_add_chunks (AXEL axel, AxStream stream, AxCount offset,
			       AxCount length);

AxCount ax_stream_write0 (AXEL axel, AxStream stream, AxCount count);
AxCount ax_stream_write (AXEL axel, AxStream stream, AxCount count,
			 AxStream data);
AxCount ax_stream_copy (AXEL axel, AxStream src, AxStream dest, AxCount count);
AxCount ax_stream_gain (AXEL axel, AxStream stream, AxCount count, AxPCM gain);
AxCount ax_stream_mix (AXEL axel, AxStream src, AxStream dest,
		       AxCount count);
AxCount ax_stream_mult (AXEL axel, AxStream src, AxStream dest,
			AxCount count);
AxCount ax_streams_mix (AXEL axel, CDList streams, AxStream dest,
			AxCount count);
AxCount ax_stream_fade (AXEL axel, AxStream src, AxStream dest, AxCount count);
AxCount ax_stream_blend (AXEL axel, AxStream src, AxStream dest,
			 AxStream blend, AxCount count);

AxCount ax_stream_interleave_2 (AXEL axel, AxStream stream,
				int name1, int name2,
				AxPCM * dest, AxCount count);
AxCount ax_stream_deinterleave_2 (AXEL axel, AxStream stream,
				  int name1, int name2,
				  AxPCM * src, AxCount count);

/* Channels */
AxChannel ax_add_channel (AXEL axel, AxStream stream, AxChannelName name);
void ax_free_channel (AXEL axel, AxChannel channel);
void ax_remove_chunk (AXEL axel, AxChunk chunk);

/* Chunks */
AxChunk ax_add_chunk (AXEL axel, AxChannel channel, AxCount length,
		      AxCount offset);
int ax_chunk_later (AXEL axel, AxChunk u1, AxChunk u2);
AxCount ax_chunk_clear (AXEL axel, AxChunk chunk);

/* SquareTone */
AxSquareTone ax_squaretone_new (AXEL axel, float frequency);
float ax_squaretone_set_frequency (AXEL axel, AxSquareTone squaretone,
				   float frequency);
float ax_squaretone_get_frequency (AXEL axel, AxSquareTone squaretone);

/* Monitor */
AxMonitor ax_monitor_new (AXEL axel);


/* Time */
AxTime ax_time_convert (AXEL axel, AxTime time, AxTimeType old_type,
			AxTimeType new_type);
AxTime ax_time_zero (AxTimeType type);
AxTime ax_time_invalid (AxTimeType type);
int ax_time_is_invalid (AxTimeType type, AxTime time);
AxTime ax_time_add (AxTimeType type, AxTime t1, AxTime t2);
AxTime ax_time_sub (AxTimeType type, AxTime t1, AxTime t2);
AxTime ax_time_min (AxTimeType type, AxTime t1, AxTime t2);
AxTime ax_time_max (AxTimeType type, AxTime t1, AxTime t2);
int ax_time_eq (AxTimeType type, AxTime t1, AxTime t2);
int ax_time_gt (AxTimeType type, AxTime t1, AxTime t2);
int ax_time_lt (AxTimeType type, AxTime t1, AxTime t2);
int ax_time_ge (AxTimeType type, AxTime t1, AxTime t2);
int ax_time_le (AxTimeType type, AxTime t1, AxTime t2);


AxCount ax_set_mixlength (AXEL axel, AxCount mixlength);
AxCount ax_get_mixlength (AXEL axel);


int ax_is_writeable (AXEL axel, AxBase base);
int ax_is_seekable (AXEL axel, AxBase base);
int ax_is_cacheable (AXEL axel, AxBase base);
int ax_is_causal (AXEL axel, AxBase base);

char * ax_set_name (AXEL axel, AxBase base, char * name);
char * ax_get_name (AXEL axel, AxBase base);

  /* XXX: Move meta out of axel.h ??? */

char * ax_meta_text_get_identifier (AXEL axel, AxMetaText mt);
char * ax_meta_text_set_identifier (AXEL axel, AxMetaText mt,
				    char * identifier);
char * ax_meta_text_get_category (AXEL axel, AxMetaText mt);
char * ax_meta_text_set_category (AXEL axel, AxMetaText mt, char * category);
char * ax_meta_text_get_description (AXEL axel, AxMetaText mt);
char * ax_meta_text_set_description (AXEL axel, AxMetaText mt,
				     char * description);
char * ax_meta_text_get_copyright (AXEL axel, AxMetaText mt);
char * ax_meta_text_set_copyright (AXEL axel, AxMetaText mt, char * copyright);
char * ax_meta_text_get_url (AXEL axel, AxMetaText mt);
char * ax_meta_text_set_url (AXEL axel, AxMetaText mt, char * url);
CDList ax_meta_text_get_authors (AXEL axel, AxMetaText mt);
void ax_meta_text_add_author (AXEL axel, AxMetaText mt, char * name,
			      char * email);

#if defined(__cplusplus)
}
#endif

#endif /* __AXEL_H__ */

