#ifndef M_MCDP_H
#define M_MCDP_H

#define MCDP_VERSION "0.6"
#define BUFSIZE 6000

#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <netdb.h>
#include <time.h>

#include "params.h"

/* libowfat */
#include "array.h"
#include "io.h"
#include "buffer.h"
#include "byte.h"
#include "fmt.h"
#include "mmap.h"
#include "open.h"
#include "scan.h"
#include "str.h"
#include "stralloc.h"
#include "tai.h"
#include "taia.h"

/* own header */
#include "db.h"
#include "env.h"
#include "dev.h"
#include "die.h"
#include "sig.h"
#include "show.h"
#include "tty.h"
#include "lang.h"

/* some header extensions */
#include "strallocX.h"
#include "typesX.h"
#include "fmtX.h"

typedef struct {
	int audio:1;  /* is it a audio track */
	int copy:1;   /* is digital copy permitted */

	u8 rnd;       /* position @ random */
	u8 lst;       /* position @ current playlist */

	u32 lba;      /* start of track */
	u16 len;      /* lba len of track */
	u32 cddb;     /* cddb trackid of current / 0=discid */

	stralloc name;   /* name of title / 0=cdname/artist */
	stralloc extd;   /* extd data for this track */
} track_t;

typedef struct {
	/* tracks @ this list (0=off, 1..99 = tracks) */
	u8 t[MCDP_CDAUDIO_MAX+1];
	u8 max;
	stralloc name;   /* name of the playlist */
} plist_t;

struct mcdp {
	int fd;         /* fd of cdrom device */

	stralloc cddbfile;  /* cddb: file of current disc */
	stralloc year;      /* cddb: year of publishing */
	stralloc genre;     /* cddb: genre */
	stralloc playorder; /* cddb: playorder */
	u32 discid;         /* cddb: the discid */
	u16 revision;       /* cddb: revision of the file */

	u32 lba;     /* for setting up a new playing command */
	u16 len;     /* for setting up a new playing command */

	u32 rel;     /* subchannel: current relative position */
	u32 abs;     /* subchannel: current absolute position */
	track_t t[MCDP_CDAUDIO_MAX+1]; /* XXX: array */

	/* times of playlist */
	u32 p_rel;   /* playlist: current relative state @ playlist */
	u32 p_abs;   /* playlist: current absolute state @ playlist */
	plist_t p[MCDP_PLIST_MAX+1]; /* XXX: array */

	u8 volume;   /* current volume of cd device (0..255) */
	u8 intro;    /* time used for the intro method (3..30) */
	u8 offset;   /* offset for drawing the tracklist */
	u8 current;  /* current playing track @ playlist */
	u8 trackmod; /* 1..9 -> used for direct access of titles via numbers */
	u8 titles;   /* number of tracks @ cdrom / playlist */

	int repeat;    /* what should be repeated */
#define R_CDROM      0 /* play whole playlist/cd in endless-loop */
#define R_TRACK      1 /* play current track in endless-loop */
#define R_OFF        2 /* play whole playlist/cd and stop */

	int ds;        /* drive status */
#define DS_NODISC    0 /* no cd inserted */
#define DS_OPEN      1 /* tray is open */
#define DS_BUSY      2 /* drive is busy */
#define DS_OKAY      3 /* we have a disc */

	int as;        /* audio status */
#define AS_PLAY      0 /* just playing */
#define AS_PAUSE     1 /* playing is paused */
#define AS_DONE      2 /* playing has just completed */
#define AS_ERROR     3 /* error while playing */
#define AS_NOSTATUS  4 /* normally no disc */

	int xs;        /* extra status */
#define XS_OPENING   0 /* opening */
#define XS_READING   1 /* reading */
#define XS_CLOSING   2 /* closing */
#define XS_NONE      3 /* no extra status */

	int db;        /* XXX: remove? */
#define DB_NOENT     0 /* no track info available */
#define DB_CDDB      1 /* some cddb info is used */

	int flags;     /* some flags, we set+use during the whole code */
#define F_M_SHUFFLE  1 /* on/off: shuffle the current list to play */

	int method;    /* current playing METHOD */
#define M_PLAY_CD    0 /* play whole cd */
#define M_PLAY_LIST  1 /* the playlist of the cddb entry */
#define M_INTRO      2 /* first cd->intro seconds of each track */

	int updates;     /* which stuff has changed */
#define U_STATUS   0x001 /* playing status updated */
#define U_METHOD   0x002 /* method is updated */
#define U_REPEAT   0x004 /* repeat is updated */
#define U_VOLUME   0x008 /* volume is updated */
#define U_MAIN     0x010 /* main window is updated (tracks, cddbp, infos...) */
#define U_TIME     0x020 /* times are updated */
#define U_DBASE    0x040 /* disc status updated */
#define U_INIT     0x080 /* really ALL is updated */
#define U_TRACKMOD 0x100 /* the trackmodifier */
#define U_DEVICE   0x200 /* name/release of cdrom drive */
#define U_ALL      0xfff /* set all updates! */

	/* current thing for show_device()
	 *
	 * 0 = Vendor + Model + Version (via scsi iquery cdb)
	 * 1 = device file (eg. /dev/scd0)
	 * 2 = device type (eg. @linux: 'scsi generic' or 'send packet')
	 */
	u8 device;

	char vendor[9]; /* vendor */
	char model[17]; /* modelname */
	char rev[5];    /* revision */
	char *driver;   /* name of driver */
	char *dev;      /* device file of cdrom device */

	/* function for sending scsi commands */
	int (*cmd)();


};

extern struct mcdp *cd;
extern array array_cds;
extern scmd_t cdb;

/* arguments to mcdp */
extern int mcdp_argc;
extern char **mcdp_argv;

extern char *mcdp_version;

extern void mcdp_init(void);
extern void mcdp_doit(void);
extern void mcdp_quit(int);
extern void mcdp_update(void);

/* aliases for working with bits @ integers */
#define isset(v,x)     (((v)&(x)) == (x))

#define set(v,x)       (v) |=  (x)
#define unset(v,x)     (v) &= ~(x)
#define toogle(v,x)    (v) ^=  (x)

#define msb(x)         (((x)>>8) & 0xff)
#define lsb(x)         ((x) & 0xff)

#define CTRL_X(x) (x-96)

#undef min
#define min(x,y) (((x)<(y))?(x):(y))

#undef max
#define max(x,y) (((x)>(y))?(x):(y))

#endif /* M_MCDP_H */

