/*
 * DATlib   Copyright (c) 1995-1996 Marcus Meissner &
 *          Friedrich-Alexander Universitaet Erlangen-Nuernberg (FAU), IMMD4
 *          All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *    This product includes software developed by Marcus Meissner
 *    at the Friedrich-Alexander Universitaet Erlangen-Nuernberg (FAU), IMMD4
 *
 * 4. The name of the University or the author may not be used
 *    to endorse or promote products derived from this software without
 *    specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND THE AUTHOR ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE UNIVERSITY OR THE AUTHOR BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#include <time.h>
/* #define LANG english */

/* defines for the dataudio_lib ... */
/* i define my own timestructures here cause the operatingsystem's ones
 * aren't exactly useable 
 */

typedef unsigned long u32;
typedef unsigned short u16;
typedef unsigned char u8;

typedef	long da_devid;

#define DA_GET_TOCENTRY 	0x4201
#define	DA_SET_TOCENTRY 	0x4202
#define	DA_LOCATE		0x4203
#define	DA_GET_PROGNR		0x4204
#define	DA_SET_PROGNR		0x4205
#define	DA_GET_PROGTIME		0x4206
#define	DA_SET_PROGTIME		0x4207
#define	DA_GET_ABSTIME		0x4208
#define	DA_SET_ABSTIME		0x4209
#define	DA_GET_RUNTIME		0x420A
#define	DA_SET_RUNTIME		0x420B
#define	DA_GET_RECORDDATE	0x420C
#define	DA_SET_RECORDDATE	0x420D
#define	DA_READ_POSITION	0x420E
#define DA_GET_CHANNELS		0x420F
#define DA_GET_SAMPLERATE	0x4210
#define DA_SET_CHANNELS		0x4211
#define DA_SET_SAMPLERATE	0x4212
#define DA_GET_PACKED		0x4213
#define DA_SET_PACKED		0x4214
#define DA_GET_ISRC		0x4215
#define DA_SET_ISRC		0x4216
#define DA_GET_CATALOG		0x4217
#define DA_SET_CATALOG		0x4218
#define DA_REWIND		0x4219
#define DA_EJECT		0x421A
#define DA_ABORT		0x421B
#define DA_GET_PRERECORDED	0x421C
#define DA_SET_PRERECORDED	0x421D
#define DA_WRITE_LEADIN		0x421E
#define DA_WRITE_LEADOUT	0x421F
#define DA_SET_TRACKNAME	0x4220
#define DA_GET_TRACKNAME	0x4221
#define DA_SET_TRACKTIME	0x4222
#define DA_GET_TRACKTIME	0x4223

struct	da_subid {
	u32	emphasis:2;
	u32	samplerate:2;
#define DA_SUBID_SAMPLERATE_48KHZ	0
#define DA_SUBID_SAMPLERATE_441KHZ	1
#define DA_SUBID_SAMPLERATE_32KHZ	2
	u32	channels:2;
#define DA_SUBID_CHANNELS_2	0
#define DA_SUBID_CHANNELS_4	1
	u32	encoding:2;
#define DA_SUBID_ENCODING_16	0
#define DA_SUBID_ENCODING_12	1
	u32	width	:2;
#define DA_SUBID_WIDTH_NORMAL	0
#define DA_SUBID_WIDTH_WIDE	1
	u32	scms	:2;
#define DA_SUBID_SCMS_ALLOWED	0
#define DA_SUBID_SCMS_DENIED	2
	u32	datapacket:2;
};
#define DA_TOC_START	100
#define DA_TOC_END	101
#define DA_TOC_ENTRIES	102

struct da_time {
	u8	indexnr;
	u8	hour;
	u8	minute;
	u8	second;
	u8	frame;
};

union _da_loc_un {
	struct	da_time	time;
	int	prognr;
};

struct da_locate {
	u8	type;
	u8	nextop;
	union	_da_loc_un u;
};

#define DA_LOC_PROGNR	0
#define DA_LOC_ABSTIME	1
#define DA_LOC_RECTIME	2
#define DA_LOC_PROGTIME	3

#define DA_LOC_NEXTOP_READ	0
#define DA_LOC_NEXTOP_WRITE	1

struct da_position {
	u32	prognr;
	u8	indexnr;
	struct	da_time	progtime;
	struct	da_time	abstime;
	struct	da_time	runtime;
};

struct da_date {
	u8	weekday;
	u8	year;
	u8	month;
	u8	day;
	u8	hour;
	u8	minute;
	u8	second;
};

struct	da_catalognr {
	u8	nr[14];
};

struct	da_isrc	{
	u32	country;
	u32	producer;	/* urheber */
	u8	year;
	u32	serialnr;
};

struct	da_tocentry {
	u32	prognr;
#define DA_TOC_AA	0xaa
#define DA_TOC_BB	0xbb
#define DA_TOC_CC	0xcc
#define DA_TOC_EE	0xee
#define DA_TOC_B0	0xb0
#define DA_TOC_A0	0xa0
#define DA_TOC_A1	0xa1
#define DA_TOC_C0	0xc0
#define DA_TOC_C1	0xc1
	u8	value;
	u8	hour;
	u8	minute;
	u8	second;
	u8	frame;
	char	*name;
};

struct	da_trackname {
	int	prognr;
	char	*name;
	int	namelen;
};

struct da_file_header {
	u32	magic;          /* magic number */
	u32	hdr_size;       /* size of this header */
	u32	data_size;      /* length of data (optional) */
	u32	encoding;       /* data encoding format */
	u32	sample_rate;    /* samples per second */
	u32	channels;       /* number of interleaved channels */

	u32	prognr;
	struct	da_time		abstime;
	struct	da_time		runtime;
	struct	da_date		recorddate;
	struct	da_catalognr	catalog;
	struct	da_isrc		isrc;
};

/* callback definitions */
enum da_cb_type {
	DA_CB_SAMPLERATE,
	DA_CB_CHANNELS,
	DA_CB_PROGTIME,
	DA_CB_RUNTIME,
	DA_CB_ABSTIME,
	DA_CB_RECORDDATE,
	DA_CB_PROGNR,
	DA_CB_SUBID,
	DA_CB_TOC,
	DA_CB_TRACKTIME,
	DA_CB_TRACKNAME,
};
/* callback granularity
 * in increasing order (required)
 */
enum da_cb_granularity {
	DA_CB_FRAMES,
	DA_CB_SECONDS,
	DA_CB_MINUTES,
	DA_CB_HOURS,
	DA_CB_DAYS,
	DA_CB_MONTHS,
	DA_CB_YEARS,
	DA_CB_WEEKDAYS,
	DA_CB_INDEXNR,
};

#define DA_CB_PROTO	int devid,enum da_cb_type type,union da_callback_data *data

struct _da_toc {
	int	tocentries;
	struct	da_tocentry	*toc;
};
union	da_callback_data {
	int	prognr;
	int	samplerate;
	int	channels;
	struct	da_subid subid;
	struct	da_time	time;
	struct	da_date	date;
	struct	_da_toc toc;
	char	*trackname;
} ;

struct	da_callback {
	union da_callback_data		data;
	enum	da_cb_type		type;
	enum	da_cb_granularity	granularity;
	struct	da_callback		*next;
	int				id;
	int				lasttimevalid;
};

#define	DA_V_READ_OR_WRITTEN	1
#define DA_V_INTOC		2
#define DA_V_INJUMP		4
#define DA_V_INSTART		8
#define DA_V_JUMPZONE		16
#define DA_V_HAVE_CATALOG	32
#define DA_V_HAVE_ISRC		64
#define DA_V_STATE_LOADED	128
#define DA_V_HAVE_PTIME		256
#define DA_V_HAVE_ATIME		512
#define DA_V_HAVE_RTIME		1024
#define DA_V_HAVE_RDATE		2048
#define DA_V_IN_LOCATE		4096
#define DA_V_LOC_WAIT_FOR_CHANGE 8192
#define DA_V_TOC_CHANGED	16384
#define DA_V_PRERECORDED	32768
#define DA_V_TRACKTIME		65536
#define DA_V_TRACKNAME		131072

struct da_state {
	u32			values;	/* bitmask, which values were set*/
	u32			bnr,mute;
	u32			cur_toc,cnt_jump,cnt_start,cnt_toc;
	int			lastlocsame;
	struct	da_position	lastreadpos;
	struct da_callback	*cb;	/* callback chain */

	u8			*writebuffer;
	u32			writecurlen;/* how much in writebuffer*/
	u8			*readbuffer;
	u32			readcurlen;

	char*			devname;
	u32			openflags;/* flags passed on open */

	da_devid		id;

	/* global state */
	u32			prognr;	/* this value is global anyway */
	struct	da_time		abstime;
	struct	da_catalognr	catalog;
	struct	da_isrc		isrc;
	struct	da_time		runtime;
	struct	da_date		recorddate;
	
	/* local state */
	struct	da_subid	subid;
	struct	da_time		progtime;

	u32			tocentries;	/* how may entries in *toc*/
	struct	da_tocentry	*toc;
	u32			toccurrent;	/* used while writing */
	u32			toctowrite;	/* frames to stay at this ent */
	struct	da_trackname	*trackname;	/* tracknames */
	u32			nroftracknames;
	char			*_track_name;/* current read/written track */
	u32			_track_curlen;/* current len/maximal len */
	u32			_track_curtrack;/* current track */

	char			*curtrackname;	/* current trackname */
	char			*_curtrackname; /* copy of this one */
	u32			_curtracknamelen; /* saved len of this one */
	struct	da_time		curtracktime;	/* current tracktime */

	caddr_t			ifdata;	/* interface specific data */
};
#define bcdinc(x) x=_bcdinc(x)

int l2bcd(int arg);
int bcd2l(int arg);
int _bcdinc(int arg);
void cdate (long t,struct tm *tm);

/* protohypes */
int	da_open(char *fn,int mode);
int	da_init(int fd,int mode);
int	da_downinit(int fd,int mode,char *fn,struct da_state *st);
int	da_downopen(char *xid,int mode);
int	da_write(int devid,unsigned char *buf,int size);
int	da_downwrite(int devid,unsigned char *buf,int size);
int	da_read(int devid,unsigned char *buf,int size);
int	da_downread(int devid,unsigned char *buf,int size);
int	da_close(int devid);
int	da_downclose(int devid);
int	da_add_callback(int devid,enum da_cb_type type,enum da_cb_granularity granularity,void (*cbfun)(DA_CB_PROTO));
int	da_up_add_callback(int devid,int cbid,enum da_cb_type type,enum da_cb_granularity gran);
int	da_down_callback(int devid,int cbid,union da_callback_data *data);
void	*da_alloc(int size);
void	da_free(void *data,int memsize);
void	*da_realloc(void *data,int newsize);
int	da_downcontrol(int devid,int type,long arg);
int	da_control(int devid,int type,long arg);
struct	da_state *da_lookup(int id);
void	da_toc_add(struct da_state *st,struct da_tocentry *te,int flag);
void da_toc_update(struct da_state*st);
