/**********************************************************************************************************************************
*
*   OpenAL cross platform audio library
*   Copyright (c) 2006, Apple Computer, Inc. All rights reserved.
*
*   Redistribution and use in source and binary forms, with or without modification, are permitted provided 
*   that the following conditions are met:
*
*   1.  Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 
*   2.  Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following 
*       disclaimer in the documentation and/or other materials provided with the distribution. 
*   3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of its contributors may be used to endorse or promote 
*       products derived from this software without specific prior written permission. 
*
*   THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 
*   THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS 
*   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 
*   TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
*   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 
*   USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
**********************************************************************************************************************************/

#ifndef __OAL_CAPTURE_DEVICE__
#define __OAL_CAPTURE_DEVICE__

#include "oalImp.h"
#include <CoreAudio/AudioHardware.h>
#include <AudioToolbox/AudioToolbox.h>
#include <AudioUnit/AudioUnit.h>
#include <map>
#include  "CAStreamBasicDescription.h"
#include  "CABufferList.h"
     
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// OALCaptureDevices
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

#pragma mark _____OALCaptureDevice_____
class OALCaptureDevice
{
#pragma mark __________ Public_Class_Members
	public:

	OALCaptureDevice(const char* 	 inDeviceName, uintptr_t   inSelfToken, UInt32 inSampleRate, UInt32 inFormat, UInt32 inBufferSize);
	~OALCaptureDevice();
	
	void				StartCapture();
	void				StopCapture();

	OSStatus			GetFrames(UInt32 inFrameCount, UInt8*	inBuffer);
	UInt32				AvailableFrames();
	void				SetError(ALenum errorCode);
	ALenum				GetError();

#pragma mark __________ Private_Class_Members

	private:
		uintptr_t						mSelfToken;
		ALenum							mCurrentError;
		bool							mCaptureOn;
		SInt64							mStoreSampleTime;				// increment on each read in the input proc, and pass to the ring buffer class when writing, reset on each stop
		SInt64							mFetchSampleTime;				// increment on each read in the input proc, and pass to the ring buffer class when writing, reset on each stop
		AudioUnit						mInputUnit;
		CAStreamBasicDescription		mNativeFormat;
		CAStreamBasicDescription		mRequestedFormat;
		CAStreamBasicDescription		mOutputFormat;
		OALRingBuffer*					mRingBuffer;					// the ring buffer
		UInt8*							mBufferData;
		AudioConverterRef				mAudioConverter;
		Float64							mSampleRateRatio;
		UInt32							mRequestedRingFrames;			
		CABufferList*					mAudioInputPtrs;

	void				InitializeAU (const char* 	inDeviceName);
	static OSStatus		InputProc(	void *						inRefCon,
									AudioUnitRenderActionFlags *ioActionFlags,
									const AudioTimeStamp *		inTimeStamp,
									UInt32 						inBusNumber,
									UInt32 						inNumberFrames,
									AudioBufferList *			ioData);
									
	static OSStatus		ACComplexInputDataProc	(AudioConverterRef				inAudioConverter,
												 UInt32							*ioNumberDataPackets,
												 AudioBufferList				*ioData,
												 AudioStreamPacketDescription	**outDataPacketDescription,
												 void*							inUserData);
										
};

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#pragma mark _____OALCaptureDeviceMap_____
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class OALCaptureDeviceMap : std::multimap<uintptr_t, OALCaptureDevice*, std::less<uintptr_t> > {
public:
    
    void Add (const	uintptr_t	inDeviceToken, OALCaptureDevice **inDevice)  {
		iterator it = upper_bound(inDeviceToken);
		insert(it, value_type (inDeviceToken, *inDevice));
	}

    OALCaptureDevice* Get(uintptr_t	inDeviceToken) {
        iterator	it = find(inDeviceToken);
        if (it != end())
            return ((*it).second);
		return (NULL);
    }
    
    void Remove (const	uintptr_t	inDeviceToken) {
        iterator 	it = find(inDeviceToken);
        if (it != end())
            erase(it);
    }
	
    UInt32 Size () const { return size(); }
    bool Empty () const { return empty(); }
};


#endif
