1 /*
2      File: AUBase.h
3  Abstract: Part of CoreAudio Utility Classes
4   Version: 1.1
5 
6  Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
7  Inc. ("Apple") in consideration of your agreement to the following
8  terms, and your use, installation, modification or redistribution of
9  this Apple software constitutes acceptance of these terms.  If you do
10  not agree with these terms, please do not use, install, modify or
11  redistribute this Apple software.
12 
13  In consideration of your agreement to abide by the following terms, and
14  subject to these terms, Apple grants you a personal, non-exclusive
15  license, under Apple's copyrights in this original Apple software (the
16  "Apple Software"), to use, reproduce, modify and redistribute the Apple
17  Software, with or without modifications, in source and/or binary forms;
18  provided that if you redistribute the Apple Software in its entirety and
19  without modifications, you must retain this notice and the following
20  text and disclaimers in all such redistributions of the Apple Software.
21  Neither the name, trademarks, service marks or logos of Apple Inc. may
22  be used to endorse or promote products derived from the Apple Software
23  without specific prior written permission from Apple.  Except as
24  expressly stated in this notice, no other rights or licenses, express or
25  implied, are granted by Apple herein, including but not limited to any
26  patent rights that may be infringed by your derivative works or by other
27  works in which the Apple Software may be incorporated.
28 
29  The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
30  MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
31  THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
32  FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
33  OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
34 
35  IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
36  OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
37  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
38  INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
39  MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
40  AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
41  STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
42  POSSIBILITY OF SUCH DAMAGE.
43 
44  Copyright (C) 2014 Apple Inc. All Rights Reserved.
45 
46 */
47 #ifndef __AUBase_h__
48 #define __AUBase_h__
49 
50 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
51 
52 #include <TargetConditionals.h>
53 #include <juce_core/native/juce_mac_ClangBugWorkaround.h>
54 
55 #if TARGET_OS_MAC
56 	#include <pthread.h>
57 #elif TARGET_OS_WIN32
58 	#include <windows.h>
59 #else
60 	#error Unsupported Operating System
61 #endif
62 
63 #include <vector>
64 
65 #include "AUScopeElement.h"
66 #include "AUInputElement.h"
67 #include "AUOutputElement.h"
68 #include "AUBuffer.h"
69 #include "CAMath.h"
70 #include "CAThreadSafeList.h"
71 #include "CAVectorUnit.h"
72 #include "CAMutex.h"
73 #if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
74 	#include <AudioUnit/AudioUnit.h>
75 	#if !CA_BASIC_AU_FEATURES
76 		#include <AudioUnit/MusicDevice.h>
77 	#endif
78 #else
79 	#include "AudioUnit.h"
80 	#if !CA_BASIC_AU_FEATURES
81 		#include "MusicDevice.h"
82 	#endif
83 #endif
84 
85 #ifndef AUTRACE
86 	#define AUTRACE(code, obj, a, b, c, d)
87 #endif
88 
89 #include "AUPlugInDispatch.h"
90 
91 
92 
93 // ________________________________________________________________________
94 // These are to be moved to the public AudioUnit headers
95 
96 #define kAUDefaultSampleRate		44100.0
97 #if !TARGET_OS_WIN32
98 #define kAUDefaultMaxFramesPerSlice	1156
99 //this allows enough default frames for a 512 dest 44K and SRC from 96K
100 // add a padding of 4 frames for any altivec rounding
101 #else
102 #define kAUDefaultMaxFramesPerSlice	2048
103 #endif
104 
105 // ________________________________________________________________________
106 
107 /*! @class AUBase */
108 class AUBase : public ComponentBase {
109 public:
110 
111 	/*! @ctor AUBase */
112 								AUBase(					AudioComponentInstance			inInstance,
113 														UInt32							numInputElements,
114 														UInt32							numOutputElements,
115 														UInt32							numGroupElements = 0);
116 	/*! @dtor AUBase */
117 	virtual						~AUBase();
118 
119 	/*! @method PostConstructor */
PostConstructor()120 	virtual void				PostConstructor() { CreateElements(); }
121 
122 	/*! @method PreDestructor */
123 	virtual void				PreDestructor();
124 
125 	/*! @method CreateElements */
126 	void						CreateElements();
127 									// Called immediately after construction, when virtual methods work.
128 									// Or, a subclass may call this in order to have access to elements
129 									// in its constructor.
130 
131 	/*! @method CreateExtendedElements */
CreateExtendedElements()132 	virtual void CreateExtendedElements() {}
133 
134 #pragma mark -
135 #pragma mark AU dispatch
136 	// ________________________________________________________________________
137 	// Virtual methods (mostly) directly corresponding to the entry points.  Many of these
138 	// have useful implementations here and will not need overriding.
139 
140 	/*! @method DoInitialize */
141 			OSStatus			DoInitialize();
142 				// this implements the entry point and makes sure that initialization
143 				// is only attempted exactly once...
144 
145 	/*! @method Initialize */
146 	virtual OSStatus			Initialize();
147 				// ... so that overrides to this method can assume that they will only
148 				// be called exactly once.
149 
150 	/*! @method IsInitialized */
IsInitialized()151 			bool				IsInitialized() const { return mInitialized; }
152 	/*! @method HasBegunInitializing */
HasBegunInitializing()153 			bool				HasBegunInitializing() const { return mHasBegunInitializing; }
154 
155 	/*! @method DoCleanup */
156 			void				DoCleanup();
157 				// same pattern as with Initialize
158 
159 	/*! @method Cleanup */
160 	virtual void				Cleanup();
161 
162 	/*! @method Reset */
163 	virtual OSStatus			Reset(					AudioUnitScope 					inScope,
164 														AudioUnitElement 				inElement);
165 
166 	// Note about GetPropertyInfo, GetProperty, SetProperty:
167 	// Certain properties are trapped out in these dispatch functions and handled with different virtual
168 	// methods.  (To discourage hacks and keep vtable size down, these are non-virtual)
169 
170 	/*! @method DispatchGetPropertyInfo */
171 			OSStatus			DispatchGetPropertyInfo(AudioUnitPropertyID				inID,
172 														AudioUnitScope					inScope,
173 														AudioUnitElement				inElement,
174 														UInt32 &						outDataSize,
175 														Boolean &						outWritable);
176 
177 	/*! @method DispatchGetProperty */
178 			OSStatus			DispatchGetProperty(	AudioUnitPropertyID 			inID,
179 														AudioUnitScope 					inScope,
180 														AudioUnitElement			 	inElement,
181 														void *							outData);
182 
183 	/*! @method DispatchSetProperty */
184 			OSStatus			DispatchSetProperty(	AudioUnitPropertyID 			inID,
185 														AudioUnitScope 					inScope,
186 														AudioUnitElement 				inElement,
187 														const void *					inData,
188 														UInt32 							inDataSize);
189 
190 			OSStatus			DispatchRemovePropertyValue(	AudioUnitPropertyID 	inID,
191 														AudioUnitScope 					inScope,
192 														AudioUnitElement 				inElement);
193 
194 	/*! @method GetPropertyInfo */
195 	virtual OSStatus			GetPropertyInfo(		AudioUnitPropertyID				inID,
196 														AudioUnitScope					inScope,
197 														AudioUnitElement				inElement,
198 														UInt32 &						outDataSize,
199 														Boolean &						outWritable);
200 
201 	/*! @method GetProperty */
202 	virtual OSStatus			GetProperty(			AudioUnitPropertyID 			inID,
203 														AudioUnitScope 					inScope,
204 														AudioUnitElement			 	inElement,
205 														void *							outData);
206 
207 	/*! @method SetProperty */
208 	virtual OSStatus			SetProperty(			AudioUnitPropertyID 			inID,
209 														AudioUnitScope 					inScope,
210 														AudioUnitElement 				inElement,
211 														const void *					inData,
212 														UInt32 							inDataSize);
213 
214 	/*! @method ClearPropertyUsage */
215 	virtual OSStatus			RemovePropertyValue (	AudioUnitPropertyID		 		inID,
216 														AudioUnitScope 					inScope,
217 														AudioUnitElement 				inElement);
218 
219 	/*! @method AddPropertyListener */
220 	virtual OSStatus			AddPropertyListener(	AudioUnitPropertyID				inID,
221 														AudioUnitPropertyListenerProc	inProc,
222 														void *							inProcRefCon);
223 
224 	/*! @method RemovePropertyListener */
225 	virtual OSStatus			RemovePropertyListener(	AudioUnitPropertyID				inID,
226 														AudioUnitPropertyListenerProc	inProc,
227 														void *							inProcRefCon,
228 														bool							refConSpecified);
229 
230 	/*! @method SetRenderNotification */
231 	virtual OSStatus			SetRenderNotification(	AURenderCallback		 		inProc,
232 														void *							inRefCon);
233 
234 	/*! @method RemoveRenderNotification */
235 	virtual OSStatus			RemoveRenderNotification(
236 														AURenderCallback		 		inProc,
237 														void *							inRefCon);
238 
239 	/*! @method GetParameter */
240 	virtual OSStatus 	GetParameter(			AudioUnitParameterID			inID,
241 														AudioUnitScope 					inScope,
242 														AudioUnitElement 				inElement,
243 														AudioUnitParameterValue &		outValue);
244 
245 	/*! @method SetParameter */
246 	virtual OSStatus 	SetParameter(			AudioUnitParameterID			inID,
247 														AudioUnitScope 					inScope,
248 														AudioUnitElement 				inElement,
249 														AudioUnitParameterValue			inValue,
250 														UInt32							inBufferOffsetInFrames);
251 
252 	/*! @method CanScheduleParams */
253 	virtual bool CanScheduleParameters() const = 0;
254 
255 	/*! @method ScheduleParameter */
256 	virtual OSStatus 	ScheduleParameter (		const AudioUnitParameterEvent 	*inParameterEvent,
257 														UInt32							inNumEvents);
258 
259 
260 	/*! @method DoRender */
261 	OSStatus 	DoRender(								AudioUnitRenderActionFlags &	ioActionFlags,
262 														const AudioTimeStamp &			inTimeStamp,
263 														UInt32							inBusNumber,
264 														UInt32							inNumberFrames,
265 														AudioBufferList &				ioData);
266 
267 
268 	/*! @method Process */
269 	OSStatus	DoProcess (							AudioUnitRenderActionFlags  &		ioActionFlags,
270 													const AudioTimeStamp &				inTimeStamp,
271 													UInt32								inFramesToProcess,
272 													AudioBufferList &					ioData);
273 
274 	/*! @method ProcessMultiple */
275 	OSStatus	DoProcessMultiple (					AudioUnitRenderActionFlags  &		ioActionFlags,
276 													const AudioTimeStamp &				inTimeStamp,
277 													UInt32								inFramesToProcess,
278 													UInt32								inNumberInputBufferLists,
279 													const AudioBufferList **			inInputBufferLists,
280 													UInt32 								inNumberOutputBufferLists,
281 													AudioBufferList **					ioOutputBufferLists);
282 
283 	/*! @method ProcessBufferLists */
ProcessBufferLists(AudioUnitRenderActionFlags & ioActionFlags,const AudioBufferList & inBuffer,AudioBufferList & outBuffer,UInt32 inFramesToProcess)284 	virtual OSStatus	ProcessBufferLists(			AudioUnitRenderActionFlags &		ioActionFlags,
285 													const AudioBufferList &				inBuffer,
286 													AudioBufferList &					outBuffer,
287 													UInt32								inFramesToProcess )
288 						{
289 							return kAudio_UnimplementedError;
290 						}
291 
292 	/*! @method ProcessMultipleBufferLists */
ProcessMultipleBufferLists(AudioUnitRenderActionFlags & ioActionFlags,UInt32 inFramesToProcess,UInt32 inNumberInputBufferLists,const AudioBufferList ** inInputBufferLists,UInt32 inNumberOutputBufferLists,AudioBufferList ** ioOutputBufferLists)293 	virtual OSStatus	ProcessMultipleBufferLists(	AudioUnitRenderActionFlags &		ioActionFlags,
294 													UInt32								inFramesToProcess,
295 												    UInt32								inNumberInputBufferLists,
296 												    const AudioBufferList **			inInputBufferLists,
297 												    UInt32							 	inNumberOutputBufferLists,
298 												    AudioBufferList **					ioOutputBufferLists)
299 						{
300 							return kAudio_UnimplementedError;
301 						}
302 
303 	/*! @method ComplexRender */
ComplexRender(AudioUnitRenderActionFlags & ioActionFlags,const AudioTimeStamp & inTimeStamp,UInt32 inOutputBusNumber,UInt32 inNumberOfPackets,UInt32 * outNumberOfPackets,AudioStreamPacketDescription * outPacketDescriptions,AudioBufferList & ioData,void * outMetadata,UInt32 * outMetadataByteSize)304 	virtual OSStatus	ComplexRender(				AudioUnitRenderActionFlags &		ioActionFlags,
305 													const AudioTimeStamp &				inTimeStamp,
306 													UInt32								inOutputBusNumber,
307 													UInt32								inNumberOfPackets,
308 													UInt32 *							outNumberOfPackets,
309 													AudioStreamPacketDescription *		outPacketDescriptions,
310 													AudioBufferList &					ioData,
311 													void *								outMetadata,
312 													UInt32 *							outMetadataByteSize)
313 						{
314 							return kAudio_UnimplementedError;
315 						}
316 
317 	// Override this method if your AU processes multiple output busses completely independently --
318 	// you'll want to just call Render without the NeedsToRender check.
319 	// Otherwise, override Render().
320 	//
321 	// N.B. Implementations of this method can assume that the output's buffer list has already been
322 	// prepared and access it with GetOutput(inBusNumber)->GetBufferList() instead of
323 	// GetOutput(inBusNumber)->PrepareBuffer(nFrames) -- if PrepareBuffer is called, a
324 	// copy may occur after rendering.
325 	/*! @method RenderBus */
RenderBus(AudioUnitRenderActionFlags & ioActionFlags,const AudioTimeStamp & inTimeStamp,UInt32 inBusNumber,UInt32 inNumberFrames)326 	virtual OSStatus			RenderBus(				AudioUnitRenderActionFlags &	ioActionFlags,
327 														const AudioTimeStamp &			inTimeStamp,
328 														UInt32							inBusNumber,
329 														UInt32							inNumberFrames)
330 								{
331 									if (NeedsToRender(inTimeStamp))
332 										return Render(ioActionFlags, inTimeStamp, inNumberFrames);
333 									return noErr;	// was presumably already rendered via another bus
334 								}
335 
336 	// N.B. For a unit with only one output bus, it can assume in its implementation of this
337 	// method that the output's buffer list has already been prepared and access it with
338 	// GetOutput(0)->GetBufferList() instead of GetOutput(0)->PrepareBuffer(nFrames)
339 	//  -- if PrepareBuffer is called, a copy may occur after rendering.
340 	/*! @method Render */
Render(AudioUnitRenderActionFlags & ioActionFlags,const AudioTimeStamp & inTimeStamp,UInt32 inNumberFrames)341 	virtual OSStatus			Render(					AudioUnitRenderActionFlags &	ioActionFlags,
342 														const AudioTimeStamp &			inTimeStamp,
343 														UInt32							inNumberFrames)
344 								{
345 									return noErr;
346 								}
347 
348 
349 #pragma mark -
350 #pragma mark Property Dispatch
351 
352 	static const Float64 kNoLastRenderedSampleTime;
353 
354 	// ________________________________________________________________________
355 	// These are generated from DispatchGetProperty/DispatchGetPropertyInfo/DispatchSetProperty
356 
357 	/*! @method BusCountWritable */
BusCountWritable(AudioUnitScope inScope)358 	virtual bool				BusCountWritable(		AudioUnitScope					inScope)
359 								{
360 									return false;
361 								}
362 	virtual OSStatus			SetBusCount(		AudioUnitScope					inScope,
363 													UInt32							inCount);
364 
365 	/*! @method SetConnection */
366 	virtual OSStatus			SetConnection(			const AudioUnitConnection &		inConnection);
367 
368 	/*! @method SetInputCallback */
369 	virtual OSStatus			SetInputCallback(		UInt32							inPropertyID,
370 														AudioUnitElement 				inElement,
371 														AURenderCallback				inProc,
372 														void *							inRefCon);
373 
374 	/*! @method GetParameterList */
375 	virtual OSStatus			GetParameterList(		AudioUnitScope					inScope,
376 														AudioUnitParameterID *			outParameterList,
377 														UInt32 &						outNumParameters);
378 															// outParameterList may be a null pointer
379 
380 	/*! @method GetParameterInfo */
381 	virtual OSStatus			GetParameterInfo(		AudioUnitScope					inScope,
382 														AudioUnitParameterID			inParameterID,
383 														AudioUnitParameterInfo &		outParameterInfo);
384 
385 	virtual OSStatus			GetParameterHistoryInfo(AudioUnitScope					inScope,
386 														AudioUnitParameterID			inParameterID,
387 														Float32 &						outUpdatesPerSecond,
388 														Float32 &						outHistoryDurationInSeconds);
389 
390 	/*! @method SaveState */
391 	virtual OSStatus			SaveState(				CFPropertyListRef *				outData);
392 
393     /*! @method SaveExtendedScopes */
SaveExtendedScopes(CFMutableDataRef outData)394 	virtual void                SaveExtendedScopes(		CFMutableDataRef				outData) {};
395 
396 	/*! @method RestoreState */
397 	virtual OSStatus			RestoreState(			CFPropertyListRef				inData);
398 
399 	/*! @method GetParameterValueStrings */
400 	virtual OSStatus			GetParameterValueStrings(AudioUnitScope					inScope,
401 														AudioUnitParameterID			inParameterID,
402 														CFArrayRef *					outStrings);
403 
404 	/*! @method CopyClumpName */
405 	virtual OSStatus			CopyClumpName(			AudioUnitScope					inScope,
406 														UInt32							inClumpID,
407 														UInt32							inDesiredNameLength,
408 														CFStringRef *					outClumpName);
409 
410 	/*! @method GetPresets */
411 	virtual OSStatus			GetPresets (			CFArrayRef * 					outData) const;
412 
413 		// set the default preset for the unit -> the number of the preset MUST be >= 0
414 		// and the name should be valid, or the preset WON'T take
415 	/*! @method SetAFactoryPresetAsCurrent */
416 	bool						SetAFactoryPresetAsCurrent (const AUPreset & inPreset);
417 
418 		// Called when someone sets a new, valid preset
419 		// If this is a valid preset, then the subclass sets its state to that preset
420 		// and returns noErr.
421 		// If not a valid preset, return an error, and the pre-existing preset is restored
422 	/*! @method NewFactoryPresetSet */
423 	virtual OSStatus			NewFactoryPresetSet (const AUPreset & inNewFactoryPreset);
424 
425 	/*! @method NewCustomPresetSet */
426 	virtual OSStatus            NewCustomPresetSet (const AUPreset & inNewCustomPreset);
427 
428 #if !CA_USE_AUDIO_PLUGIN_ONLY
429 	/*! @method GetNumCustomUIComponents */
430 	virtual int					GetNumCustomUIComponents ();
431 
432 	/*! @method GetUIComponentDescs */
433 	virtual void				GetUIComponentDescs (ComponentDescription* inDescArray);
434 #endif
435 
436 	/*! @method CopyIconLocation */
437 	virtual CFURLRef			CopyIconLocation ();
438 
439 	// default is no latency, and unimplemented tail time
440 	/*! @method GetLatency */
GetLatency()441     virtual Float64				GetLatency() {return 0.0;}
442 	/*! @method GetTailTime */
GetTailTime()443     virtual Float64				GetTailTime() {return 0;}
444 	/*! @method SupportsRampAndTail */
SupportsTail()445 	virtual	bool				SupportsTail () { return false; }
446 
447 	/*! @method IsStreamFormatWritable */
448 			bool				IsStreamFormatWritable(	AudioUnitScope					scope,
449 														AudioUnitElement				element);
450 
451 	/*! @method StreamFormatWritable */
452 	virtual bool				StreamFormatWritable(	AudioUnitScope					scope,
453 														AudioUnitElement				element) = 0;
454 															// scope will always be input or output
455 
456 			// pass in a pointer to get the struct, and num channel infos
457 			// you can pass in NULL to just get the number
458 			// a return value of 0 (the default in AUBase) means the property is not supported...
459 	/*! @method SupportedNumChannels */
460 	virtual UInt32				SupportedNumChannels (	const AUChannelInfo**			outInfo);
461 
462 	/*! @method ValidFormat */
463 	virtual bool				ValidFormat(			AudioUnitScope					inScope,
464 														AudioUnitElement				inElement,
465 														const CAStreamBasicDescription & inNewFormat);
466 															// Will only be called after StreamFormatWritable
467 															// has succeeded.
468 															// Default implementation requires canonical format:
469 															// native-endian 32-bit float, any sample rate,
470 															// any number of channels; override when other
471 															// formats are supported.  A subclass's override can
472 															// choose to always return true and trap invalid
473 															// formats in ChangeStreamFormat.
474 
475 
476 	/*! @method FormatIsCanonical */
477 			bool				FormatIsCanonical(		const CAStreamBasicDescription &format);
478 
479 	/*! @method MakeCanonicalFormat */
480 			void				MakeCanonicalFormat(	CAStreamBasicDescription &	outDesc,
481 														int							numChannels = 2);
482 
483 	/*! @method GetStreamFormat */
484 	virtual const CAStreamBasicDescription &
485 								GetStreamFormat(		AudioUnitScope					inScope,
486 														AudioUnitElement				inElement);
487 
488 	/*! @method ChangeStreamFormat */
489 	virtual	OSStatus			ChangeStreamFormat(		AudioUnitScope					inScope,
490 														AudioUnitElement				inElement,
491 														const CAStreamBasicDescription & inPrevFormat,
492 														const CAStreamBasicDescription & inNewFormat);
493 															// Will only be called after StreamFormatWritable
494 															// and ValidFormat have succeeded.
495 
496 	// ________________________________________________________________________
497 
498 #if !CA_USE_AUDIO_PLUGIN_ONLY
499 	/*! @method ComponentEntryDispatch */
500 	static OSStatus			ComponentEntryDispatch(	ComponentParameters *			params,
501 														AUBase *						This);
502 #endif
503 
504 	// ________________________________________________________________________
505 	// Methods useful for subclasses
506 
507 	/*! @method GetScope */
GetScope(AudioUnitScope inScope)508 	AUScope &					GetScope(				AudioUnitScope					inScope)
509 	{
510 		if (inScope >= kNumScopes) {
511 			AUScope * scope = GetScopeExtended(inScope);
512 			if (!scope) COMPONENT_THROW(kAudioUnitErr_InvalidScope);
513 			return *scope;
514 		}
515 		return mScopes[inScope];
516 	}
517 
518 	/*! @method GetScopeExtended */
GetScopeExtended(AudioUnitScope inScope)519 	virtual AUScope *			GetScopeExtended (AudioUnitScope inScope) { return NULL; }
520 
521 	/*! @method GlobalScope */
GlobalScope()522 	AUScope &					GlobalScope() { return mScopes[kAudioUnitScope_Global]; }
523 	/*! @method Inputs */
Inputs()524 	AUScope &					Inputs()	{ return mScopes[kAudioUnitScope_Input]; }
525 	/*! @method Outputs */
Outputs()526 	AUScope &					Outputs()	{ return mScopes[kAudioUnitScope_Output]; }
527 #if !CA_BASIC_AU_FEATURES
528 	/*! @method Groups */
Groups()529 	AUScope &					Groups()	{ return mScopes[kAudioUnitScope_Group]; }
530 #endif
531 	/*! @method Globals */
Globals()532 	AUElement *					Globals()	{ return mScopes[kAudioUnitScope_Global].GetElement(0); }
533 
534 	/*! @method SetNumberOfElements */
535 	void						SetNumberOfElements(	AudioUnitScope					inScope,
536 														UInt32							numElements);
537 
538 	/*! @method GetElement */
GetElement(AudioUnitScope inScope,AudioUnitElement inElement)539 	AUElement *					GetElement(				AudioUnitScope 					inScope,
540 														AudioUnitElement			 	inElement)
541 	{
542 		return GetScope(inScope).GetElement(inElement);
543 	}
544 
545 	/*! @method GetIOElement */
GetIOElement(AudioUnitScope inScope,AudioUnitElement inElement)546 	AUIOElement *				GetIOElement(			AudioUnitScope 					inScope,
547 														AudioUnitElement			 	inElement)
548 	{
549 		return GetScope(inScope).GetIOElement(inElement);
550 	}
551 
552 	/*! @method SafeGetElement */
SafeGetElement(AudioUnitScope inScope,AudioUnitElement inElement)553 	AUElement *					SafeGetElement(			AudioUnitScope 					inScope,
554 														AudioUnitElement			 	inElement)
555 	{
556 		return GetScope(inScope).SafeGetElement(inElement);
557 	}
558 
559 	/*! @method GetInput */
GetInput(AudioUnitElement inElement)560 	AUInputElement *			GetInput(				AudioUnitElement				inElement)
561 	{
562 		return static_cast<AUInputElement *>(Inputs().SafeGetElement(inElement));
563 	}
564 
565 	/*! @method GetOutput */
GetOutput(AudioUnitElement inElement)566 	AUOutputElement *			GetOutput(				AudioUnitElement				inElement)
567 	{
568 		return static_cast<AUOutputElement *>(Outputs().SafeGetElement(inElement));
569 	}
570 
571 #if !CA_BASIC_AU_FEATURES
572 	/*! @method GetGroup */
GetGroup(AudioUnitElement inElement)573 	AUElement *					GetGroup(				AudioUnitElement				inElement)
574 	{
575 		return Groups().SafeGetElement(inElement);
576 	}
577 #endif
578 
579 	/*! @method PullInput */
PullInput(UInt32 inBusNumber,AudioUnitRenderActionFlags & ioActionFlags,const AudioTimeStamp & inTimeStamp,UInt32 inNumberFrames)580 	OSStatus					PullInput(				UInt32	 					inBusNumber,
581 														AudioUnitRenderActionFlags &ioActionFlags,
582 														const AudioTimeStamp &		inTimeStamp,
583 														UInt32						inNumberFrames)
584 	{
585 		AUInputElement *input = GetInput(inBusNumber);	// throws if error
586 		return input->PullInput(ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames);
587 	}
588 
589 	/*! @method GetMaxFramesPerSlice */
GetMaxFramesPerSlice()590 	UInt32						GetMaxFramesPerSlice() const { return mMaxFramesPerSlice; }
591 	/*! @method UsesFixedBlockSize */
UsesFixedBlockSize()592 	bool						UsesFixedBlockSize() const { return mUsesFixedBlockSize; }
593 	/*! @method SetUsesFixedBlockSize */
SetUsesFixedBlockSize(bool inUsesFixedBlockSize)594 	void						SetUsesFixedBlockSize(bool inUsesFixedBlockSize) { mUsesFixedBlockSize = inUsesFixedBlockSize; }
595 
596 	/*! @method GetVectorUnitType */
GetVectorUnitType()597 	static SInt32				GetVectorUnitType() { return sVectorUnitType; }
598 	/*! @method HasVectorUnit */
HasVectorUnit()599 	static bool					HasVectorUnit() { return sVectorUnitType > 0; }
600 	/*! @method HasAltivec */
HasAltivec()601 	static bool					HasAltivec() { return sVectorUnitType == kVecAltivec; }
602 	/*! @method HasSSE2 */
HasSSE2()603 	static bool					HasSSE2() { return sVectorUnitType >= kVecSSE2; }
604 	/*! @method HasSSE3 */
HasSSE3()605 	static bool					HasSSE3() { return sVectorUnitType >= kVecSSE3; }
606 
607 	/*! @method AudioUnitAPIVersion */
AudioUnitAPIVersion()608 	UInt8						AudioUnitAPIVersion() const { return mAudioUnitAPIVersion; }
609 
610 	/*! @method IsRenderThread */
InRenderThread()611 	bool						InRenderThread () const
612 								{
613 #if TARGET_OS_MAC
614 									return (mRenderThreadID ? pthread_equal (mRenderThreadID, pthread_self()) : false);
615 #elif TARGET_OS_WIN32
616 									return (mRenderThreadID ? mRenderThreadID == GetCurrentThreadId() : false);
617 #endif
618 								}
619 
620 	/*! @method HasInput */
HasInput(AudioUnitElement inElement)621 	bool						HasInput(				AudioUnitElement				inElement) {
622 									AUInputElement *in = static_cast<AUInputElement *>(Inputs().GetElement(inElement));
623 									return in != NULL && in->IsActive();
624 								}
625 									// says whether an input is connected or has a callback
626 
627 	/*! @method PropertyChanged */
628 	virtual void				PropertyChanged(		AudioUnitPropertyID				inID,
629 														AudioUnitScope					inScope,
630 														AudioUnitElement				inElement);
631 
632 #if !CA_NO_AU_UI_FEATURES
633 	// These calls can be used to call a Host's Callbacks. The method returns -1 if the host
634 	// hasn't supplied the callback. Any other result is returned by the host.
635 	// As in the API contract, for a parameter's value, you specify a pointer
636 	// to that data type. Specify NULL for a parameter that you are not interested
637 	// as this can save work in the host.
638 
639 	/*! @method CallHostBeatAndTempo */
CallHostBeatAndTempo(Float64 * outCurrentBeat,Float64 * outCurrentTempo)640 	OSStatus	CallHostBeatAndTempo (Float64				*outCurrentBeat,
641 										Float64				*outCurrentTempo)
642 	{
643 		return (mHostCallbackInfo.beatAndTempoProc
644 						? (*mHostCallbackInfo.beatAndTempoProc) (mHostCallbackInfo.hostUserData,
645 																	outCurrentBeat,
646 																	outCurrentTempo)
647 						: -1);
648 	}
649 
650 	/*! @method CallHostMusicalTimeLocation */
CallHostMusicalTimeLocation(UInt32 * outDeltaSampleOffsetToNextBeat,Float32 * outTimeSig_Numerator,UInt32 * outTimeSig_Denominator,Float64 * outCurrentMeasureDownBeat)651 	OSStatus	CallHostMusicalTimeLocation (UInt32  		*outDeltaSampleOffsetToNextBeat,
652 										Float32           	*outTimeSig_Numerator,
653 										UInt32            	*outTimeSig_Denominator,
654 										Float64           	*outCurrentMeasureDownBeat)
655 	{
656 		return (mHostCallbackInfo.musicalTimeLocationProc
657 						? (*mHostCallbackInfo.musicalTimeLocationProc) (mHostCallbackInfo.hostUserData,
658 																			outDeltaSampleOffsetToNextBeat,
659 																			outTimeSig_Numerator,
660 																			outTimeSig_Denominator,
661 																			outCurrentMeasureDownBeat)
662 						: -1);
663 	}
664 
665 	/*! @method CallHostTransportState */
CallHostTransportState(Boolean * outIsPlaying,Boolean * outTransportStateChanged,Float64 * outCurrentSampleInTimeLine,Boolean * outIsCycling,Float64 * outCycleStartBeat,Float64 * outCycleEndBeat)666 	OSStatus	CallHostTransportState (Boolean 			*outIsPlaying,
667 										Boolean 			*outTransportStateChanged,
668 										Float64 			*outCurrentSampleInTimeLine,
669 										Boolean 			*outIsCycling,
670 										Float64 			*outCycleStartBeat,
671 										Float64 			*outCycleEndBeat)
672 	{
673 		return (mHostCallbackInfo.transportStateProc
674 						? (*mHostCallbackInfo.transportStateProc) (mHostCallbackInfo.hostUserData,
675 																		outIsPlaying,
676 																		outTransportStateChanged,
677 																		outCurrentSampleInTimeLine,
678 																		outIsCycling,
679 																		outCycleStartBeat,
680 																		outCycleEndBeat)
681 						: -1);
682 	}
683 #endif
684 
685 	char*						GetLoggingString () const;
686 
GetMutex()687 	CAMutex*					GetMutex() { return mAUMutex; }
688 
689 	// ________________________________________________________________________
690 	/*! @method CreateElement */
691 	virtual AUElement *			CreateElement(			AudioUnitScope					scope,
692 														AudioUnitElement				element);
693 
694 #pragma mark -
695 #pragma mark AU Output Base Dispatch
696 	// ________________________________________________________________________
697 	// ________________________________________________________________________
698 	// ________________________________________________________________________
699 	// output unit methods
700 	/*! @method Start */
Start()701 	virtual OSStatus	Start() { return kAudio_UnimplementedError; }
702 	/*! @method Stop */
Stop()703 	virtual OSStatus	Stop() { return kAudio_UnimplementedError; }
704 
705 #if !CA_BASIC_AU_FEATURES
706 #pragma mark -
707 #pragma mark AU Music Base Dispatch
708 
709 #if !TARGET_OS_IPHONE
710 // these methods are deprecated, so we don't include them except for compatability
711 	/*! @method PrepareInstrument */
PrepareInstrument(MusicDeviceInstrumentID inInstrument)712 	virtual OSStatus			PrepareInstrument(MusicDeviceInstrumentID inInstrument) { return kAudio_UnimplementedError; }
713 
714 	/*! @method PrepareInstrument */
ReleaseInstrument(MusicDeviceInstrumentID inInstrument)715 	virtual OSStatus			ReleaseInstrument(MusicDeviceInstrumentID inInstrument) { return kAudio_UnimplementedError; }
716 #endif
717 
718 	// ________________________________________________________________________
719 	// ________________________________________________________________________
720 	// ________________________________________________________________________
721 	// music device/music effect methods -- incomplete
722 	/*! @method MIDIEvent */
MIDIEvent(UInt32 inStatus,UInt32 inData1,UInt32 inData2,UInt32 inOffsetSampleFrame)723 	virtual OSStatus	MIDIEvent(		UInt32 						inStatus,
724 										UInt32 						inData1,
725 										UInt32 						inData2,
726 										UInt32 						inOffsetSampleFrame) { return kAudio_UnimplementedError; }
727 
728 	/*! @method SysEx */
SysEx(const UInt8 * inData,UInt32 inLength)729 	virtual OSStatus	SysEx(			const UInt8 *				inData,
730 										UInt32 						inLength) { return kAudio_UnimplementedError;}
731 
732 	/*! @method StartNote */
StartNote(MusicDeviceInstrumentID inInstrument,MusicDeviceGroupID inGroupID,NoteInstanceID * outNoteInstanceID,UInt32 inOffsetSampleFrame,const MusicDeviceNoteParams & inParams)733 	virtual OSStatus	StartNote(		MusicDeviceInstrumentID 	inInstrument,
734 										MusicDeviceGroupID 			inGroupID,
735 										NoteInstanceID *			outNoteInstanceID,
736 										UInt32 						inOffsetSampleFrame,
737 										const MusicDeviceNoteParams &inParams) { return kAudio_UnimplementedError; }
738 
739 	/*! @method StopNote */
StopNote(MusicDeviceGroupID inGroupID,NoteInstanceID inNoteInstanceID,UInt32 inOffsetSampleFrame)740 	virtual OSStatus	StopNote(		MusicDeviceGroupID 			inGroupID,
741 										NoteInstanceID 				inNoteInstanceID,
742 										UInt32 						inOffsetSampleFrame) { return kAudio_UnimplementedError; }
743 #endif
744 
745 	// ________________________________________________________________________
746 	// ________________________________________________________________________
747 	// ________________________________________________________________________
748 
749 protected:
750 #pragma mark -
751 #pragma mark Implementation methods
752 
753 	/*! @method ReallocateBuffers */
754 	virtual void				ReallocateBuffers();
755 									// needs to be called when mMaxFramesPerSlice changes
756 	virtual void				DeallocateIOBuffers();
757 
758 	/*! @method FillInParameterName */
FillInParameterName(AudioUnitParameterInfo & ioInfo,CFStringRef inName,bool inShouldRelease)759 	static void					FillInParameterName (AudioUnitParameterInfo& ioInfo, CFStringRef inName, bool inShouldRelease)
760 	{
761 		ioInfo.cfNameString = inName;
762 		ioInfo.flags |= kAudioUnitParameterFlag_HasCFNameString;
763 		if (inShouldRelease)
764 			ioInfo.flags |= kAudioUnitParameterFlag_CFNameRelease;
765 		CFStringGetCString (inName, ioInfo.name, offsetof (AudioUnitParameterInfo, clumpID), kCFStringEncodingUTF8);
766 	}
767 
HasClump(AudioUnitParameterInfo & ioInfo,UInt32 inClumpID)768 	static void					HasClump (AudioUnitParameterInfo& ioInfo, UInt32 inClumpID)
769 	{
770 		ioInfo.clumpID = inClumpID;
771 		ioInfo.flags |= kAudioUnitParameterFlag_HasClump;
772 	}
773 
774 	/*! @method SetMaxFramesPerSlice */
775 	virtual void				SetMaxFramesPerSlice(UInt32 nFrames);
776 
777 	/*! @method CanSetMaxFrames */
778 	virtual OSStatus			CanSetMaxFrames() const;
779 
780 	/*! @method WantsRenderThreadID */
WantsRenderThreadID()781 	bool						WantsRenderThreadID () const { return mWantsRenderThreadID; }
782 
783 	/*! @method SetWantsRenderThreadID */
784 	void						SetWantsRenderThreadID (bool inFlag);
785 
786 	/*! @method SetRenderError */
SetRenderError(OSStatus inErr)787 	OSStatus					SetRenderError (OSStatus inErr)
788 	{
789 		if (inErr && mLastRenderError == 0) {
790 			mLastRenderError = inErr;
791 			PropertyChanged(kAudioUnitProperty_LastRenderError, kAudioUnitScope_Global, 0);
792 		}
793 		return inErr;
794 	}
795 
796 private:
797 	/*! @method DoRenderBus */
798 	// shared between Render and RenderSlice, inlined to minimize function call overhead
DoRenderBus(AudioUnitRenderActionFlags & ioActionFlags,const AudioTimeStamp & inTimeStamp,UInt32 inBusNumber,AUOutputElement * theOutput,UInt32 inNumberFrames,AudioBufferList & ioData)799 	OSStatus					DoRenderBus(			AudioUnitRenderActionFlags &	ioActionFlags,
800 														const AudioTimeStamp &			inTimeStamp,
801 														UInt32							inBusNumber,
802 														AUOutputElement *				theOutput,
803 														UInt32							inNumberFrames,
804 														AudioBufferList &				ioData)
805 	{
806         if (theOutput != NULL)
807         {
808             if (ioData.mBuffers[0].mData == NULL || (theOutput->WillAllocateBuffer() && Outputs().GetNumberOfElements() > 1))
809                 // will render into cache buffer
810                 theOutput->PrepareBuffer(inNumberFrames);
811             else
812                 // will render into caller's buffer
813                 theOutput->SetBufferList(ioData);
814         }
815 
816 		OSStatus result = RenderBus(ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames);
817 		if (result == noErr && theOutput != NULL) {
818 			if (ioData.mBuffers[0].mData == NULL) {
819 				theOutput->CopyBufferListTo(ioData);
820 				AUTRACE(kCATrace_AUBaseDoRenderBus, mComponentInstance, inNumberFrames, (intptr_t)theOutput->GetBufferList().mBuffers[0].mData, 0, *(UInt32 *)ioData.mBuffers[0].mData);
821 			} else {
822 				theOutput->CopyBufferContentsTo(ioData);
823 				AUTRACE(kCATrace_AUBaseDoRenderBus, mComponentInstance, inNumberFrames, (intptr_t)theOutput->GetBufferList().mBuffers[0].mData, (intptr_t)ioData.mBuffers[0].mData, *(UInt32 *)ioData.mBuffers[0].mData);
824 				theOutput->InvalidateBufferList();
825 			}
826 		}
827 		return result;
828 	}
829 
830 	/*! @method HasIcon */
831 	bool						HasIcon ();
832 
833 	/*! @method ResetRenderTime */
ResetRenderTime()834 	void						ResetRenderTime ()
835 								{
836 									memset (&mCurrentRenderTime, 0, sizeof(mCurrentRenderTime));
837 									mCurrentRenderTime.mSampleTime = kNoLastRenderedSampleTime;
838 								}
839 
840 protected:
841 	/*! @method GetAudioChannelLayout */
842 	virtual UInt32				GetChannelLayoutTags(	AudioUnitScope				scope,
843 														AudioUnitElement 			element,
844 														AudioChannelLayoutTag *		outLayoutTags);
845 
846 	/*! @method GetAudioChannelLayout */
847 	virtual UInt32				GetAudioChannelLayout(	AudioUnitScope				scope,
848 														AudioUnitElement 			element,
849 														AudioChannelLayout *		outLayoutPtr,
850 														Boolean &					outWritable);
851 
852 	/*! @method SetAudioChannelLayout */
853 	virtual OSStatus			SetAudioChannelLayout(	AudioUnitScope 				scope,
854 														AudioUnitElement 			element,
855 														const AudioChannelLayout *	inLayout);
856 
857 	/*! @method RemoveAudioChannelLayout */
858 	virtual OSStatus			RemoveAudioChannelLayout(AudioUnitScope scope, AudioUnitElement element);
859 
860 	/*! @method NeedsToRender */
NeedsToRender(const AudioTimeStamp & inTimeStamp)861 	bool						NeedsToRender(			const AudioTimeStamp &		inTimeStamp)
862 								{
863 									bool needsToRender = fnotequal(inTimeStamp.mSampleTime, mCurrentRenderTime.mSampleTime);
864 									if (needsToRender)	// only copy this if we need to render
865 										mCurrentRenderTime = inTimeStamp;
866 									return needsToRender;
867 								}
868 
869 	// Scheduled parameter implementation:
870 
871 	typedef std::vector<AudioUnitParameterEvent> ParameterEventList;
872 
873 	// Usually, you won't override this method.  You only need to call this if your DSP code
874 	// is prepared to handle scheduled immediate and ramped parameter changes.
875 	// Before calling this method, it is assumed you have already called PullInput() on the input busses
876 	// for which the DSP code depends.  ProcessForScheduledParams() will call (potentially repeatedly)
877 	// virtual method ProcessScheduledSlice() to perform the actual DSP for a given sub-division of
878 	// the buffer.  The job of ProcessForScheduledParams() is to sub-divide the buffer into smaller
879 	// pieces according to the scheduled times found in the ParameterEventList (usually coming
880 	// directly from a previous call to ScheduleParameter() ), setting the appropriate immediate or
881 	// ramped parameter values for the corresponding scopes and elements, then calling ProcessScheduledSlice()
882 	// to do the actual DSP for each of these divisions.
883 	virtual OSStatus 	ProcessForScheduledParams(	ParameterEventList		&inParamList,
884 															UInt32					inFramesToProcess,
885 															void					*inUserData );
886 
887 	//	This method is called (potentially repeatedly) by ProcessForScheduledParams()
888 	//	in order to perform the actual DSP required for this portion of the entire buffer
889 	//	being processed.  The entire buffer can be divided up into smaller "slices"
890 	//	according to the timestamps on the scheduled parameters...
891 	//
892 	//	sub-classes wishing to handle scheduled parameter changes should override this method
893 	//  in order to do the appropriate DSP.  AUEffectBase already overrides this for standard
894 	//	effect AudioUnits.
ProcessScheduledSlice(void * inUserData,UInt32 inStartFrameInBuffer,UInt32 inSliceFramesToProcess,UInt32 inTotalBufferFrames)895 	virtual OSStatus			ProcessScheduledSlice(	void				*inUserData,
896 														UInt32				inStartFrameInBuffer,
897 														UInt32				inSliceFramesToProcess,
898 														UInt32				inTotalBufferFrames ) {return noErr;};	// default impl does nothing...
899 
900 
901 	/*! @method CurrentRenderTime */
CurrentRenderTime()902 	const AudioTimeStamp &		CurrentRenderTime () const { return mCurrentRenderTime; }
903 
904 	// ________________________________________________________________________
905 	//	Private data members to discourage hacking in subclasses
906 private:
907 	struct RenderCallback {
RenderCallbackRenderCallback908 		RenderCallback(AURenderCallback proc, void *ref) :
909 			mRenderNotify(proc),
910 			mRenderNotifyRefCon(ref)
911 		{ }
912 
913 		AURenderCallback			mRenderNotify;
914 		void *						mRenderNotifyRefCon;
915 
916 		bool operator == (const RenderCallback &other) {
917 			return this->mRenderNotify == other.mRenderNotify &&
918 					this->mRenderNotifyRefCon == other.mRenderNotifyRefCon;
919 		}
920 	};
921 	typedef TThreadSafeList<RenderCallback>	RenderCallbackList;
922 
923 #if !CA_BASIC_AU_FEATURES
924 	enum { kNumScopes = 4 };
925 #else
926 	enum { kNumScopes = 3 };
927 #endif
928 
929 	/*! @var mElementsCreated */
930 	bool						mElementsCreated;
931 protected:
932 	/*! @var mInitialized */
933 	bool						mInitialized;
934 	/*! @var mHasBegunInitializing */
935 	bool						mHasBegunInitializing;
936 private:
937 	/*! @var mAudioUnitAPIVersion */
938 	UInt8						mAudioUnitAPIVersion;
939 
940 	/*! @var mInitNumInputEls */
941 	const UInt32				mInitNumInputEls;
942 	/*! @var mInitNumOutputEls */
943 	const UInt32				mInitNumOutputEls;
944 #if !CA_BASIC_AU_FEATURES
945 	/*! @var mInitNumGroupEls */
946 	const UInt32				mInitNumGroupEls;
947 #endif
948 	/*! @var mScopes */
949 	AUScope						mScopes[kNumScopes];
950 
951 	/*! @var mRenderCallbacks */
952 	RenderCallbackList			mRenderCallbacks;
953 	bool						mRenderCallbacksTouched;
954 
955 	/*! @var mRenderThreadID */
956 #if TARGET_OS_MAC
957 	pthread_t					mRenderThreadID;
958 #elif TARGET_OS_WIN32
959 	UInt32						mRenderThreadID;
960 #endif
961 
962 	/*! @var mWantsRenderThreadID */
963 	bool						mWantsRenderThreadID;
964 
965 	/*! @var mCurrentRenderTime */
966 	AudioTimeStamp				mCurrentRenderTime;
967 
968 	/*! @var mMaxFramesPerSlice */
969 	UInt32						mMaxFramesPerSlice;
970 
971 	/*! @var mLastRenderError */
972 	OSStatus					mLastRenderError;
973 	/*! @var mCurrentPreset */
974 	AUPreset					mCurrentPreset;
975 
976 protected:
977 	/*! @var mUsesFixedBlockSize */
978 	bool						mUsesFixedBlockSize;
979 
980 	struct PropertyListener {
981 		AudioUnitPropertyID				propertyID;
982 		AudioUnitPropertyListenerProc	listenerProc;
983 		void *							listenerRefCon;
984 	};
985 	typedef std::vector<PropertyListener>	PropertyListeners;
986 
987 	/*! @var mParamList */
988 	ParameterEventList			mParamList;
989 	/*! @var mPropertyListeners */
990 	PropertyListeners			mPropertyListeners;
991 
992 	/*! @var mBuffersAllocated */
993 	bool						mBuffersAllocated;
994 
995 	/*! @var mLogString */
996 	// if this is NOT null, it will contain identifying info about this AU.
997 	char*						mLogString;
998 
999 	/*! @var mNickName */
1000 	CFStringRef					mNickName;
1001 
1002 	/*! @var mAUMutex */
1003 	CAMutex *					mAUMutex;
1004 
1005 private:
1006 	/*! @var sVectorUnitType */
1007 	static SInt32	sVectorUnitType;
1008 
1009 #if !CA_NO_AU_HOST_CALLBACKS
1010 protected:
1011 	/*! @var mHostCallbackInfo */
1012 	HostCallbackInfo 			mHostCallbackInfo;
1013 
1014 #endif
1015 #if !CA_NO_AU_UI_FEATURES
1016 protected:
1017 	/*! @var mContextInfo */
1018 	CFStringRef					mContextName;
1019 #endif
1020 };
1021 
PullInputWithBufferList(AudioUnitRenderActionFlags & ioActionFlags,const AudioTimeStamp & inTimeStamp,AudioUnitElement inElement,UInt32 nFrames,AudioBufferList * inBufferList)1022 inline 	OSStatus	AUInputElement::PullInputWithBufferList(
1023 												AudioUnitRenderActionFlags &  	ioActionFlags,
1024 												const AudioTimeStamp &			inTimeStamp,
1025 												AudioUnitElement				inElement,
1026 												UInt32							nFrames,
1027 												AudioBufferList *				inBufferList)
1028 {
1029 	OSStatus theResult;
1030 
1031 	if (HasConnection()) {
1032 			// only support connections for V2 audio units
1033 #if !CA_USE_AUDIO_PLUGIN_ONLY
1034 		if (mConnRenderProc != NULL)
1035 			theResult = reinterpret_cast<AudioUnitRenderProc>(mConnRenderProc)(
1036 							mConnInstanceStorage, &ioActionFlags, &inTimeStamp, mConnection.sourceOutputNumber, nFrames, inBufferList);
1037 		else
1038 #endif
1039 			theResult = AudioUnitRender(
1040 							mConnection.sourceAudioUnit, &ioActionFlags, &inTimeStamp, mConnection.sourceOutputNumber, nFrames, inBufferList);
1041 	} else {
1042 		// kFromCallback:
1043 			theResult = (mInputProc)(
1044 							mInputProcRefCon, &ioActionFlags, &inTimeStamp, inElement, nFrames, inBufferList);
1045 	}
1046 
1047 	if (mInputType == kNoInput)	// defense: the guy upstream could have disconnected
1048 								// it's a horrible thing to do, but may happen!
1049 		return kAudioUnitErr_NoConnection;
1050 
1051 
1052 	return theResult;
1053 }
1054 
1055 #endif // __AUBase_h__
1056