1/**********************************************************************************************************************************
2*
3*   OpenAL cross platform audio library
4*   Copyright (c) 2005, Apple Computer, Inc. All rights reserved.
5*
6*   Redistribution and use in source and binary forms, with or without modification, are permitted provided
7*   that the following conditions are met:
8*
9*   1.  Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
10*   2.  Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
11*       disclaimer in the documentation and/or other materials provided with the distribution.
12*   3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of its contributors may be used to endorse or promote
13*       products derived from this software without specific prior written permission.
14*
15*   THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16*   THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS
17*   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
18*   TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
19*   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
20*   USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
21*
22**********************************************************************************************************************************/
23
24#ifndef __OAL_CAPTURE_DEVICE__
25#define __OAL_CAPTURE_DEVICE__
26
27#include "oalImp.h"
28#include "CAStreamBasicDescription.h"
29#include "CABufferList.h"
30
31#include <CoreAudio/AudioHardware.h>
32#include <AudioToolbox/AudioToolbox.h>
33#include <AudioUnit/AudioUnit.h>
34#include <map>
35#include <libkern/OSAtomic.h>
36
37#define LOG_CAPTUREDEVICE_VERBOSE         0
38
39// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
40// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
41// OALCaptureDevices
42// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
43// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
44
45#pragma mark _____OALCaptureDevice_____
46class OALCaptureDevice
47{
48#pragma mark __________ Public_Class_Members
49	public:
50
51	OALCaptureDevice(const char* 	 inDeviceName, uintptr_t   inSelfToken, UInt32 inSampleRate, UInt32 inFormat, UInt32 inBufferSize);
52	~OALCaptureDevice();
53
54	void				StartCapture();
55	void				StopCapture();
56
57	OSStatus			GetFrames(UInt32 inFrameCount, UInt8*	inBuffer);
58	UInt32				AvailableFrames();
59	void				SetError(ALenum errorCode);
60	ALenum				GetError();
61
62	// we need to mark the capture device if it is being used to prevent deletion from another thread
63	void				SetInUseFlag()		{ OSAtomicIncrement32Barrier(&mInUseFlag); }
64	void				ClearInUseFlag()	{ OSAtomicDecrement32Barrier(&mInUseFlag); }
65	volatile int32_t	IsInUse()			{ return mInUseFlag; }
66
67#pragma mark __________ Private_Class_Members
68
69	private:
70#if LOG_CAPTUREDEVICE_VERBOSE
71		uintptr_t						mSelfToken;
72#endif
73		ALenum							mCurrentError;
74		bool							mCaptureOn;
75		SInt64							mStoreSampleTime;				// increment on each read in the input proc, and pass to the ring buffer class when writing, reset on each stop
76		SInt64							mFetchSampleTime;				// increment on each read in the input proc, and pass to the ring buffer class when writing, reset on each stop
77		AudioUnit						mInputUnit;
78		CAStreamBasicDescription		mNativeFormat;
79		CAStreamBasicDescription		mRequestedFormat;
80		CAStreamBasicDescription		mOutputFormat;
81		OALRingBuffer*					mRingBuffer;					// the ring buffer
82		UInt8*							mBufferData;
83		AudioConverterRef				mAudioConverter;
84		Float64							mSampleRateRatio;
85		UInt32							mRequestedRingFrames;
86		CABufferList*					mAudioInputPtrs;
87		volatile int32_t				mInUseFlag;						// flag to indicate the device is currently being used by one or more threads
88
89	void				InitializeAU (const char* 	inDeviceName);
90	static OSStatus		InputProc(	void *						inRefCon,
91									AudioUnitRenderActionFlags *ioActionFlags,
92									const AudioTimeStamp *		inTimeStamp,
93									UInt32 						inBusNumber,
94									UInt32 						inNumberFrames,
95									AudioBufferList *			ioData);
96
97	static OSStatus		ACComplexInputDataProc	(AudioConverterRef				inAudioConverter,
98												 UInt32							*ioNumberDataPackets,
99												 AudioBufferList				*ioData,
100												 AudioStreamPacketDescription	**outDataPacketDescription,
101												 void*							inUserData);
102
103};
104
105// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
106#pragma mark _____OALCaptureDeviceMap_____
107// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
108class OALCaptureDeviceMap : std::multimap<uintptr_t, OALCaptureDevice*, std::less<uintptr_t> > {
109public:
110
111    void Add (const	uintptr_t	inDeviceToken, OALCaptureDevice **inDevice)  {
112		iterator it = upper_bound(inDeviceToken);
113		insert(it, value_type (inDeviceToken, *inDevice));
114	}
115
116    OALCaptureDevice* Get(uintptr_t	inDeviceToken) {
117        iterator	it = find(inDeviceToken);
118        if (it != end())
119            return ((*it).second);
120		return (NULL);
121    }
122
123    void Remove (const	uintptr_t	inDeviceToken) {
124        iterator 	it = find(inDeviceToken);
125        if (it != end())
126            erase(it);
127    }
128
129    UInt32 Size () const { return size(); }
130    bool Empty () const { return empty(); }
131};
132
133
134#endif
135