/*=============================================================================
	CAAudioFileStreamer.h
	
	$Log: CAAudioFileStreamer.h,v $
	Revision 1.7  2004/11/18 00:25:34  dwyatt
	fix GetCurrentFrame so afplay can be told to play portions of a file
	
	Revision 1.6  2004/10/15 17:10:34  dwyatt
	CAAudioFile rewrite to use ExtAudioFile (changeable via compile flag in CAAudioFile.h)
	
	Revision 1.5  2004/09/30 21:06:46  jcm10
	update an argument name
	
	Revision 1.4  2004/05/27 19:51:54  dwyatt
	reinstate SetFile methods which allowed wrapping an existing CAAudioFile
	
	Revision 1.3  2004/05/26 00:36:02  dwyatt
	track change to CABufferQueue; writer/recorder now create their own CAAudioFile's from scratch instead of wrapping the client's [3666988]
	
	Revision 1.2  2004/01/31 01:50:38  dwyatt
	track CAAudioFile changes
	
	Revision 1.1  2004/01/14 00:08:09  dwyatt
	moved from Source/Tests/AudioFileUtility/Utility
	
	Revision 1.7  2003/12/04 00:59:02  dwyatt
	refactoring
	
	Revision 1.6  2003/10/15 00:27:30  dwyatt
	refactor on top of CABufferQueue
	
	Revision 1.5  2003/10/09 23:23:13  dwyatt
	refactor/cleanup to support CAAudioFileRecorder
	
	Revision 1.4  2003/09/11 00:47:56  dwyatt
	maintain a mRunning member so that GetPosition can be accurate when we're stopped
	
	Revision 1.3  2003/08/23 04:52:23  dwyatt
	fix GetCurrentPosition so as not to report EOF until we're really there
	
	Revision 1.2  2003/07/09 19:12:41  dwyatt
	multiple I/O buffers, prepare for record
	
	Revision 1.1  2003/06/23 23:07:37  dwyatt
	initial checkin
	
	created Wed Jun 18 2003, Doug Wyatt
	Copyright (c) 2003 Apple Computer, Inc.  All Rights Reserved

	$NoKeywords: $
=============================================================================*/

#ifndef __CAAudioFileStreamer_h__
#define __CAAudioFileStreamer_h__

#include "CABufferQueue.h"
#include "CAAudioFile.h"

// ____________________________________________________________________________
// Base class for CAAudioFileReader and CAAudioFileWriter
class CAAudioFileStreamer {
public:
	CAAudioFileStreamer() : mRunning(false), mFile(NULL) { }
	virtual ~CAAudioFileStreamer() { delete mFile; }

	CAAudioFile &		GetFile() { return *mFile; }
	const CAAudioFile & GetFile() const { return *mFile; }

	bool				IsRunning() { return mRunning; }

protected:
	bool				mRunning;
	CAAudioFile *		mFile;
};

// ____________________________________________________________________________

class CAAudioFileReader : public CAPullBufferQueue, public CAAudioFileStreamer {
public:
	CAAudioFileReader(int nBuffers, UInt32 bufferSizeFrames) :
		CAPullBufferQueue(nBuffers, bufferSizeFrames) { }
	
	void				SetFile(const FSRef &inFile);
	virtual void		Start();
	virtual void		Stop();
	double				GetCurrentPosition() const;	// 0-1
	SInt64				GetCurrentFrame() const;// { return mFile->Tell(); }
	SInt64				GetNumberFrames() const { return mFile->GetNumberFrames(); }

	void				SetCurrentPosition(double loc);	// 0-1

private:
	class FileReadBuffer : public CABufferQueue::Buffer {
	public:
		FileReadBuffer(CABufferQueue *queue, const CAStreamBasicDescription &fmt, UInt32 nBytes) :
			CABufferQueue::Buffer(queue, fmt, nBytes)
		{ }
		
		void			UpdateAfterRead(SInt64 curFrame, UInt32 nFramesRead);
		void			GetLocation(UInt32 &frm0, UInt32 &frame1) const {
							frm0 = mStartFrame; frame1 = mEndFrame;
						}
		
		SInt64			mBufferStartFileFrame;
	};
	
	virtual CABufferQueue::Buffer *	CreateBuffer(const CAStreamBasicDescription &fmt, UInt32 nBytes) {
							return new FileReadBuffer(this, fmt, nBytes);
						}
	virtual void		ProcessBuffer(CABufferQueue::Buffer *b) {
							ReadBuffer(static_cast<FileReadBuffer *>(b));
						}
	void				ReadBuffer(FileReadBuffer *b);
};

// ____________________________________________________________________________

class CAAudioFileWriter : public CAPushBufferQueue, public CAAudioFileStreamer {
public:
	CAAudioFileWriter(int nBuffers, UInt32 bufferSizeFrames) :
		CAPushBufferQueue(nBuffers, bufferSizeFrames) { }

	void				SetFile(AudioFileID file);
	void				SetFile(const FSRef &parentDir, CFStringRef filename, AudioFileTypeID filetype, const CAStreamBasicDescription &dataFormat, const CAAudioChannelLayout *layout);
	virtual void		Start();
	virtual void		Stop();

private:
	virtual CABufferQueue::Buffer *	CreateBuffer(const CAStreamBasicDescription &fmt, UInt32 nBytes) {
							return new CABufferQueue::Buffer(this, fmt, nBytes);
						}
	virtual void		ProcessBuffer(CABufferQueue::Buffer *b) {
							WriteBuffer(b);
						}
	void				WriteBuffer(CABufferQueue::Buffer *b);
};

#endif // __CAAudioFileStreamer_h__
