typedef struct Worker Worker;
typedef struct Req Req;
typedef struct Fid Fid;
typedef struct File File;
typedef struct Playlist Playlist;
typedef struct Wmsg Wmsg;
typedef union Pmsg Pmsg;
typedef struct Pacbuf Pacbuf;

enum {
	Qdir,
	Qplayctl,
	Qplaylist,
	Qplayvol,
	Qplaystat,
	Nqid,
};

enum {
	DbgPcm		= 0x01000,
	DbgPac		= 0x02000,
	DbgFs		= 0x10000,
	DbgWorker	= 0x20000,
	DbgPlayer	= 0x40000,
	DbgError	= 0x80000,
};

enum {
	STACKSIZE = 2048*sizeof(void*),
	Messagesize = 8*1024+IOHDRSZ,
	Undef = 0x80000000,
	/* 256 buffers of 4096 bytes represents 5.9 seconds
	 * of playout at 44100 Hz (2*16bit samples)
	 */
	NPacbuf = 256,
	Pacbufsize = 4096,
	NSparebuf = 16,	/* For in-line commands (Pause, Resume, Error) */
};

enum {
	/* Named commands (see fs.c): */
	Nostate,	// can't use zero for state
	Error,
	Stop,
	Pause,
	Play,
	Resume,
	Skip,
	/* Unnamed commands */
	Work,
	Check,
	Flush,
	Prep,
	Preq,
};

union Pmsg {
	ulong m;
	struct{
		ushort cmd;
		ushort off;
	};
};

struct Wmsg {
	Pmsg;
	void	*arg;	/* if(cmd != Work) mallocated by sender, freed by receiver */
};

struct Playlist {
	/* The play list consists of a sequence of {objectref, filename}
	 * entries.  Object ref and file name are separated by a tab.
	 * An object ref may not contain a tab.  Entries are seperated
	 * by newline characters.  Neither file names, nor object refs
	 * may contain newlines.
	 */
	ulong	*lines;
	ulong	nlines;
	char	*data;
	ulong	ndata;
};

struct File {
	Dir	dir;
	Channel	*workers;
};

struct Worker
{
	Req	*r;
	Channel	*eventc;
};

struct Fid
{
	int	fid;
	File	*file;
	ushort	flags;
	short	readers;
	ulong	vers;	/* set to file's version when completely read */
	Fid	*next;
};

struct Req
{
	uchar	indata[Messagesize];
	uchar	outdata[Messagesize];
	Fcall	ifcall;
	Fcall	ofcall;
	Fid*	fid;
};

struct Pacbuf {
	Pmsg;
	int len;
	char data[Pacbufsize];
};

void	allocwork(Req*);
Wmsg	waitmsg(Worker*, Channel*);
int	sendmsg(Channel*, Wmsg*);
void	bcastmsg(Channel*, Wmsg*);
void	reqfree(Req*);
Req	*reqalloc(void);
void	readbuf(Req*, void*, long);
void	readstr(Req*, char*);
void	volumeset(int *v);
void	playupdate(Pmsg, char*);
void	playinit(void);
void	volumeproc(void*);
void	srv(void *);
long	robustread(int, void*, long);
void	volumeupdate(int*);
char	*getplaylist(int);
char	*getplaystat(char*, char*);

extern int		debug, aflag;
extern char	*user;
extern Channel	*playc;
extern char	*statetxt[];
extern int		volume[8];
extern Playlist	playlist;
extern Channel	*workers;
extern Channel	*volumechan;
extern Channel	*playchan;
extern Channel	*playlistreq;
extern File	files[];
extern int		srvfd[];
