#ifndef AUDIOFILE_H
#define AUDIOFILE_H

//ALWrapper: OpenAL-based audio library.
//AudioFile class: Base class, abstract, provides common attributes to all
//supported file formats.
//This class is meant to use streaming, and thus a complete copy of all data
//already read is NOT stored.

#include <string>
#include <cstdio>
#include <cerrno>
#include <cassert>
#include "AudioFileError.h"

namespace ALWrapper {

typedef std::string Buffer;
class AudioFile {
	protected:
	
		std::string filename;	//The name of the loaded file.
		std::string header;	//Raw file header.
		std::string comments;	//Any comments in the file's header.
		unsigned long filesize;	//Size of the file in bytes.
		double length;		//Length of the file in seconds.
		unsigned int bitrate;	//The bitrate of the file, in kbps.
		unsigned int frequency;	//Frequency of the audio data, in Hz.
		unsigned short channels;//Number of channels in the file.
		FILE* file;		//A stream to use with this file.

		//Opens a file and sets file to the resulting stream pointer.
		//This can fail, in which case it will throw an AudioFileError.
		//This does not fully open a file. Rather, it just performs
		//the preliminary step of going from name to stream.
		void openfile(const std::string& fname,const std::string& mode);
	public:

		//Default buffer size.
		static const unsigned long defaultbufsize;
		
		//Default constructor.
		//Creates a new AudioFile-derived class with everything
		//initialized to 0.
		//The derived classes should define other constructors.
		AudioFile();

		//Destructor. Closes any open files, deallocates buffers, etc.
		virtual ~AudioFile();

		//Pure virtual open() function. Opens a file with the given
		//name. Pure virtual because the type of data has not been
		//chosen through this class by the caller.

		//Throws an exception if an error occurs.
		virtual void open(const std::string& fname) = 0;
		virtual bool isOpen() const { return file != 0; }
		
		//Closes the currently open file. Note that this does not
		//reset information such as length; that is done on the next
		//open. The FILE pointer is nulled, however, to avoid multiple
		//deletions.
		virtual void close();

		//Reads the specified number of bytes into a buffer.
		//Throws on error.
		virtual Buffer readData(unsigned long bufsize=defaultbufsize);

		//Seek to a particular position in the file.
		virtual void seek(unsigned long pos);	//In bytes.
		virtual void seek(double seconds) = 0;		//In seconds.

		//Return the current position in the file (in bytes).
		virtual unsigned long tell();

		//Or seconds. This is type-dependent but common to all types, so
		//it becomes pure virtual.
		virtual double tellTime() = 0;
		
		//Various accessors. Be careful with the * operator.
		inline std::string getFilename() const	{ return filename; }
		inline std::string getHeader() const	{ return header; }
		inline std::string getComments() const	{ return comments; }
		inline unsigned long getSize() const { return filesize; }
		inline double getLength() const		{ return length; }
		unsigned int getBitRate() const		{ return bitrate; }
		unsigned int getFrequency()	const	{ return frequency; }
		unsigned short getChannels() const	{ return channels; }
		FILE* operator*() const			{ return file; }
		
		//Gets the bitrate of the currently playing part of the stream.
		//Pure virtual, as how to do this is implementation-dependent.
		virtual unsigned int getCurrentBitRate() = 0;
};

}	//end namespace ALWrapper

#endif	//ifndef AUDIOFILE_H

