1 /*
2 Copyright (C) 2016 Apple Inc. All Rights Reserved.
3 See LICENSE.txt for this sample’s licensing information
4 
5 Abstract:
6 Part of Core Audio AUBase Classes
7 */
8 
9 #include "ComponentBase.h"
10 #include "CAXException.h"
11 
12 #if TARGET_OS_MAC
13 pthread_mutex_t ComponentInitLocker::sComponentOpenMutex = PTHREAD_MUTEX_INITIALIZER;
14 pthread_once_t ComponentInitLocker::sOnce = PTHREAD_ONCE_INIT;
15 
InitComponentInitLocker()16 void ComponentInitLocker::InitComponentInitLocker()
17 {
18 	// have to do this because OS X lacks PTHREAD_MUTEX_RECURSIVE_INITIALIZER_NP
19 	pthread_mutexattr_t attr;
20 	pthread_mutexattr_init(&attr);
21 	pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
22 	pthread_mutex_init(&sComponentOpenMutex, &attr);
23 	pthread_mutexattr_destroy(&attr);
24 }
25 
26 #elif TARGET_OS_WIN32
27 CAGuard	ComponentInitLocker::sComponentOpenGuard("sComponentOpenGuard");
28 #endif
29 
30 ComponentBase::EInstanceType ComponentBase::sNewInstanceType;
31 
32 static OSStatus CB_GetComponentDescription (const AudioComponentInstance inInstance, AudioComponentDescription * outDesc);
33 #if !CA_USE_AUDIO_PLUGIN_ONLY && !TARGET_OS_WIN32
34 	static OSStatus CMgr_GetComponentDescription (const AudioComponentInstance inInstance, AudioComponentDescription * outDesc);
35 #endif
36 
ComponentBase(AudioComponentInstance inInstance)37 ComponentBase::ComponentBase(AudioComponentInstance inInstance)
38 	: mComponentInstance(inInstance),
39 	  mInstanceType(sNewInstanceType)
40 {
41 	GetComponentDescription();
42 }
43 
~ComponentBase()44 ComponentBase::~ComponentBase()
45 {
46 }
47 
PostConstructor()48 void			ComponentBase::PostConstructor()
49 {
50 }
51 
PreDestructor()52 void			ComponentBase::PreDestructor()
53 {
54 }
55 
56 #define ACPI	((AudioComponentPlugInInstance *)self)
57 #define ACImp	((ComponentBase *)&ACPI->mInstanceStorage)
58 
AP_Open(void * self,AudioUnit compInstance)59 OSStatus ComponentBase::AP_Open(void *self, AudioUnit compInstance)
60 {
61 	OSStatus result = noErr;
62 	try {
63 		ComponentInitLocker lock;
64 
65 		ComponentBase::sNewInstanceType = ComponentBase::kAudioComponentInstance;
66 		ComponentBase *cb = (ComponentBase *)(*ACPI->mConstruct)(&ACPI->mInstanceStorage, compInstance);
67 		cb->PostConstructor();	// allows base class to do additional initialization
68 		// once the derived class is fully constructed
69 		result = noErr;
70 	}
71 	COMPONENT_CATCH
72 	if (result)
73 		delete ACPI;
74 	return result;
75 }
76 
AP_Close(void * self)77 OSStatus ComponentBase::AP_Close(void *self)
78 {
79 	OSStatus result = noErr;
80 	try {
81 		if (ACImp) {
82 			ACImp->PreDestructor();
83 			(*ACPI->mDestruct)(&ACPI->mInstanceStorage);
84 			free(self);
85 		}
86 	}
87 	COMPONENT_CATCH
88 	return result;
89 }
90 
91 #if !CA_USE_AUDIO_PLUGIN_ONLY
Version()92 OSStatus		ComponentBase::Version()
93 {
94 	return 0x00000001;
95 }
96 
ComponentEntryDispatch(ComponentParameters * p,ComponentBase * This)97 OSStatus		ComponentBase::ComponentEntryDispatch(ComponentParameters *p, ComponentBase *This)
98 {
99 	if (This == NULL) return kAudio_ParamError;
100 
101 	OSStatus result = noErr;
102 
103 	switch (p->what) {
104 	case kComponentCloseSelect:
105 		This->PreDestructor();
106 		delete This;
107 		break;
108 
109 	case kComponentVersionSelect:
110 		result = This->Version();
111 		break;
112 
113 	case kComponentCanDoSelect:
114 		switch (GetSelectorForCanDo(p)) {
115 		case kComponentOpenSelect:
116 		case kComponentCloseSelect:
117 		case kComponentVersionSelect:
118 		case kComponentCanDoSelect:
119 			return 1;
120 		default:
121 			return 0;
122 		}
123 
124 	default:
125 		result = badComponentSelector;
126 		break;
127 	}
128 	return result;
129 }
130 
GetSelectorForCanDo(ComponentParameters * params)131 SInt16		ComponentBase::GetSelectorForCanDo(ComponentParameters *params)
132 {
133 	if (params->what != kComponentCanDoSelect) return 0;
134 
135 	#if TARGET_CPU_X86
136 		SInt16 sel = params->params[0];
137 	#elif TARGET_CPU_X86_64
138 		SInt16 sel = params->params[1];
139 	#elif TARGET_CPU_PPC
140 		SInt16 sel = (params->params[0] >> 16);
141 	#else
142 		SInt16 sel = params->params[0];
143 	#endif
144 
145 	return sel;
146 /*
147 		printf ("flags:%d, paramSize: %d, what: %d\n\t", params->flags, params->paramSize, params->what);
148 		for (int i = 0; i < params->paramSize; ++i) {
149 			printf ("[%d]:%d(0x%x), ", i, params->params[i], params->params[i]);
150 		}
151 		printf("\n\tsel:%d\n", sel);
152 */
153 }
154 
155 #endif
156 
157 #if CA_DO_NOT_USE_AUDIO_COMPONENT
158 static OSStatus ComponentBase_GetComponentDescription (const AudioComponentInstance & inInstance, AudioComponentDescription &outDesc);
159 #endif
160 
GetComponentDescription() const161 AudioComponentDescription ComponentBase::GetComponentDescription() const
162 {
163 	AudioComponentDescription desc;
164 	OSStatus result = 1;
165 
166 	if (IsPluginObject()) {
167 		ca_require_noerr(result = CB_GetComponentDescription (mComponentInstance, &desc), home);
168 	}
169 #if !CA_USE_AUDIO_PLUGIN_ONLY
170 	else {
171 		ca_require_noerr(result = CMgr_GetComponentDescription (mComponentInstance, &desc), home);
172 	}
173 #endif
174 
175 home:
176 	if (result)
177 		memset (&desc, 0, sizeof(AudioComponentDescription));
178 
179 	return desc;
180 }
181 
182 #if CA_USE_AUDIO_PLUGIN_ONLY
183 // everything we need is there and we should be linking against it
CB_GetComponentDescription(const AudioComponentInstance inInstance,AudioComponentDescription * outDesc)184 static OSStatus CB_GetComponentDescription (const AudioComponentInstance inInstance, AudioComponentDescription * outDesc)
185 {
186 	AudioComponent comp = AudioComponentInstanceGetComponent(inInstance);
187 	if (comp)
188 		return AudioComponentGetDescription(comp, outDesc);
189 
190 	return kAudio_ParamError;
191 }
192 
193 #elif !TARGET_OS_WIN32
194 // these are the direct dependencies on ComponentMgr calls that an AU
195 // that is a component mgr is dependent on
196 
197 // these are dynamically loaded so that these calls will work on Leopard
198 #include <dlfcn.h>
199 
CB_GetComponentDescription(const AudioComponentInstance inInstance,AudioComponentDescription * outDesc)200 static OSStatus CB_GetComponentDescription (const AudioComponentInstance inInstance, AudioComponentDescription * outDesc)
201 {
202 	typedef AudioComponent (*AudioComponentInstanceGetComponentProc) (AudioComponentInstance);
203 	static AudioComponentInstanceGetComponentProc aciGCProc = NULL;
204 
205 	typedef OSStatus (*AudioComponentGetDescriptionProc)(AudioComponent, AudioComponentDescription *);
206 	static AudioComponentGetDescriptionProc acGDProc = NULL;
207 
208 	static int doneInit = 0;
209 	if (doneInit == 0) {
210 		doneInit = 1;
211 		void* theImage = dlopen("/System/Library/Frameworks/AudioUnit.framework/AudioUnit", RTLD_LAZY);
212 		if (theImage != NULL)
213 		{
214 			aciGCProc = (AudioComponentInstanceGetComponentProc)dlsym (theImage, "AudioComponentInstanceGetComponent");
215 			if (aciGCProc) {
216 				acGDProc = (AudioComponentGetDescriptionProc)dlsym (theImage, "AudioComponentGetDescription");
217 			}
218 		}
219 	}
220 
221 	OSStatus result = kAudio_UnimplementedError;
222 	if (acGDProc && aciGCProc) {
223 		AudioComponent comp = (*aciGCProc)(inInstance);
224 		if (comp)
225 			result = (*acGDProc)(comp, outDesc);
226 	}
227 #if !CA_USE_AUDIO_PLUGIN_ONLY
228 	else {
229 		result = CMgr_GetComponentDescription (inInstance, outDesc);
230 	}
231 #endif
232 
233 	return result;
234 }
235 
236 #if !CA_USE_AUDIO_PLUGIN_ONLY
237 // these are the direct dependencies on ComponentMgr calls that an AU
238 // that is a component mgr is dependent on
239 
240 // these are dynamically loaded
241 
242 #include <CoreServices/CoreServices.h>
243 #include <AudioUnit/AudioUnit.h>
244 #include "CAXException.h"
245 #include "ComponentBase.h"
246 
247 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
248 // Component Manager
249 // Used for fast dispatch with audio units
250 typedef Handle (*GetComponentInstanceStorageProc)(ComponentInstance aComponentInstance);
251 static GetComponentInstanceStorageProc sGetComponentInstanceStorageProc = NULL;
252 
253 typedef OSErr (*GetComponentInfoProc)(Component, ComponentDescription *, void*, void*, void*);
254 static GetComponentInfoProc sGetComponentInfoProc = NULL;
255 
256 typedef void (*SetComponentInstanceStorageProc)(ComponentInstance, Handle);
257 static SetComponentInstanceStorageProc sSetComponentInstanceStorageProc = NULL;
258 
259 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
260 
CSInitOnce(void *)261 static void CSInitOnce(void* /*unused*/)
262 {
263 	void *theImage = dlopen("/System/Library/Frameworks/CoreServices.framework/CoreServices", RTLD_LAZY);
264 	if (!theImage) return;
265 
266 	sGetComponentInstanceStorageProc = (GetComponentInstanceStorageProc) dlsym(theImage, "GetComponentInstanceStorage");
267 	sGetComponentInfoProc = (GetComponentInfoProc)dlsym (theImage, "GetComponentInfo");
268 	sSetComponentInstanceStorageProc = (SetComponentInstanceStorageProc) dlsym(theImage, "SetComponentInstanceStorage");
269 }
270 
271 #if TARGET_OS_MAC
272 
273 #include <dispatch/dispatch.h>
274 
275 static dispatch_once_t sCSInitOnce = 0;
276 
CSInit()277 static void CSInit ()
278 {
279 	dispatch_once_f(&sCSInitOnce, NULL, CSInitOnce);
280 }
281 
282 #else
283 
CSInit()284 static void CSInit ()
285 {
286 	static int sDoCSLoad = 1;
287 	if (sDoCSLoad) {
288 		sDoCSLoad = 0;
289 		CSInitOnce(NULL);
290 	}
291 }
292 
293 #endif
294 
CMgr_GetComponentDescription(const AudioComponentInstance inInstance,AudioComponentDescription * outDesc)295 OSStatus CMgr_GetComponentDescription (const AudioComponentInstance inInstance, AudioComponentDescription * outDesc)
296 {
297 	CSInit();
298 	if (sGetComponentInfoProc)
299 		return (*sGetComponentInfoProc)((Component)inInstance, (ComponentDescription*)outDesc, NULL, NULL, NULL);
300 	return kAudio_UnimplementedError;
301 }
302 
CMgr_GetComponentInstanceStorage(ComponentInstance aComponentInstance)303 Handle CMgr_GetComponentInstanceStorage(ComponentInstance aComponentInstance)
304 {
305 	CSInit();
306 	if (sGetComponentInstanceStorageProc)
307 		return (*sGetComponentInstanceStorageProc)(aComponentInstance);
308 	return NULL;
309 }
310 
CMgr_SetComponentInstanceStorage(ComponentInstance aComponentInstance,Handle theStorage)311 void CMgr_SetComponentInstanceStorage(ComponentInstance aComponentInstance, Handle theStorage)
312 {
313 	CSInit();
314 	if (sSetComponentInstanceStorageProc)
315 		(*sSetComponentInstanceStorageProc)(aComponentInstance, theStorage);
316 }
317 #endif // !CA_USE_AUDIO_PLUGIN_ONLY
318 
319 #else
320 //#include "ComponentManagerDependenciesWin.h"
321 // everything we need is there and we should be linking against it
CB_GetComponentDescription(const AudioComponentInstance inInstance,AudioComponentDescription * outDesc)322 static OSStatus CB_GetComponentDescription (const AudioComponentInstance inInstance, AudioComponentDescription * outDesc)
323 {
324 	AudioComponent comp = AudioComponentInstanceGetComponent(inInstance);
325 	if (comp)
326 		return AudioComponentGetDescription(comp, outDesc);
327 
328 	return kAudio_ParamError;
329 }
330 
331 #endif
332 
333