#ifndef _module_h
#define _module_h

typedef struct GlobHdr GlobHdr;

#include "codec.h"

#ifdef MAKEABS
#define ogg_page_size (1<<14)
#define ogg_out_size  (1<<14)
#else
#define ogg_page_size (1<<11)
#define ogg_out_size  (1<<13)
#endif

typedef struct
{
	byte* start;
	byte* free;
	byte* data;
	byte* last;
	int   size;
	int   count;
} bytebuf;

typedef struct
{
	uint32_t size;
	volatile uint32_t real_start;
	volatile uint32_t real_free;
	volatile uint32_t finished;
	int32_t  dummy[12];
	byte     data[1];
} dinbuf;

typedef struct
{
	uint32_t real_size;
	volatile uint32_t real_start;
	volatile uint32_t real_free;
	volatile uint32_t finished;
	uint32_t size;
	int32_t  dummy[11];
	int16_t  data[1];
} doutbuf;

typedef enum
{
	  Stream_Object_OggHdr   = 0
	, Stream_Object_Comments = 1
	, Stream_Object_CodeBook = 2
	, Stream_Object_Packet   = 3
	, Stream_Object_None     = 4
} Stream_Object;

typedef enum
{
	  Stream_Decode_ReadPage        = 0
	, Stream_Decode_SyncPageOut     = 1
	, Stream_Decode_WaitPlayed      = 2
	, Stream_Decode_StreamNew       = 3
	, Stream_Decode_StreamPageIn    = 4
	, Stream_Decode_StreamPacketOut = 5
	, Stream_Decode_StreamSamples   = 6
	, Stream_Decode_Finished        = 7
	, Stream_Decode_FatalError      = 8
} Stream_Decode;

#define Stream_Flag_ForegroundProcess 0x01
#define Stream_Flag_LimitedProcess    0x02

typedef struct
{
	int16_t* start;
	int16_t* free;
	int16_t* data;
	int16_t* last;
} sndbuf;

typedef struct
{
	Stream_Object    object;
	ogg_stream_state os; // take physical pages, weld into a logical stream of packets
	ogg_packet       op; // one raw packet of data for decode
	vorbis_comment   vc; // struct that stores all the bitstream user comments
	vorbis_dsp_state vd; // central working state for the packet->PCM decoder
	vorbis_block     vb; // local working space for packet->PCM decode
	vorbis_info      vi; // struct that stores all the static vorbis bitstream settings
} vorbis_stream;

typedef struct
{
	GlobHdr*        pGlobHdr;
	// dynamic area buffers
	dinbuf*         inb;
	doutbuf*        outb;
	int             inb_area;
	int             outb_area;
	bytebuf         oggb;
	int             interlaced;
	// to check params changes on new serialno
	struct
	{
		int         channels;
		int         rate;
		int         flags;
	} conf;
	// for position past input buffer clear
	int             usedoutb;
	vorbis_stream*  poldvs;
	// output
	sndbuf          sndb;
	// main information
	Stream_Decode   decode;
	int64_t         maxgranulepos;
	int64_t         seek_pos;
	_kernel_oserror lasterr;
	// callback
	int             saved_freesndbuf;

	// work
	ogg_sync_state  oy; // sync and verify incoming physical bitstream
	ogg_page        og; // one Ogg bitstream page.  Vorbis packets are inside
	vorbis_stream*  pvs; // vorbis stream;
} stream;

void bg_task(int arg);

#endif
