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