• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 /* OpenSL ES private and global functions not associated with an interface or class */
18 
19 #include "sles_allinclusive.h"
20 
21 
22 /** \brief Return true if the specified interface exists and has been initialized for this object.
23  *  Returns false if the class does not support this kind of interface, or the class supports the
24  *  interface but this particular object has not had the interface exposed at object creation time
25  *  or by DynamicInterface::AddInterface. Note that the return value is not affected by whether
26  *  the application has requested access to the interface with Object::GetInterface. Assumes on
27  *  entry that the object is locked for either shared or exclusive access.
28  */
29 
IsInterfaceInitialized(IObject * thiz,unsigned MPH)30 bool IsInterfaceInitialized(IObject *thiz, unsigned MPH)
31 {
32     assert(NULL != thiz);
33     assert( /* (MPH_MIN <= MPH) && */ (MPH < (unsigned) MPH_MAX));
34     const ClassTable *clazz = thiz->mClass;
35     assert(NULL != clazz);
36     int index;
37     if (0 > (index = clazz->mMPH_to_index[MPH])) {
38         return false;
39     }
40     assert(MAX_INDEX >= clazz->mInterfaceCount);
41     assert(clazz->mInterfaceCount > (unsigned) index);
42     switch (thiz->mInterfaceStates[index]) {
43     case INTERFACE_EXPOSED:
44     case INTERFACE_ADDED:
45         return true;
46     default:
47         return false;
48     }
49 }
50 
51 
52 /** \brief Map an IObject to it's "object ID" (which is really a class ID) */
53 
IObjectToObjectID(IObject * thiz)54 SLuint32 IObjectToObjectID(IObject *thiz)
55 {
56     assert(NULL != thiz);
57     // Note this returns the OpenSL ES object ID in preference to the OpenMAX AL if both available
58     const ClassTable *clazz = thiz->mClass;
59     assert(NULL != clazz);
60     SLuint32 id = clazz->mSLObjectID;
61     if (!id)
62         id = clazz->mXAObjectID;
63     return id;
64 }
65 
66 
67 /** \brief Acquire a strong reference to an object.
68  *  Check that object has the specified "object ID" (which is really a class ID) and is in the
69  *  realized state.  If so, then acquire a strong reference to it and return true.
70  *  Otherwise return false.
71  */
72 
AcquireStrongRef(IObject * object,SLuint32 expectedObjectID)73 SLresult AcquireStrongRef(IObject *object, SLuint32 expectedObjectID)
74 {
75     if (NULL == object) {
76         return SL_RESULT_PARAMETER_INVALID;
77     }
78     // NTH additional validity checks on address here
79     SLresult result;
80     object_lock_exclusive(object);
81     SLuint32 actualObjectID = IObjectToObjectID(object);
82     if (expectedObjectID != actualObjectID) {
83         SL_LOGE("object %p has object ID %u but expected %u", object, actualObjectID,
84             expectedObjectID);
85         result = SL_RESULT_PARAMETER_INVALID;
86     } else if (SL_OBJECT_STATE_REALIZED != object->mState) {
87         SL_LOGE("object %p with object ID %u is not realized", object, actualObjectID);
88         result = SL_RESULT_PRECONDITIONS_VIOLATED;
89     } else {
90         ++object->mStrongRefCount;
91         result = SL_RESULT_SUCCESS;
92     }
93     object_unlock_exclusive(object);
94     return result;
95 }
96 
97 
98 /** \brief Release a strong reference to an object.
99  *  Entry condition: the object is locked.
100  *  Exit condition: the object is unlocked.
101  *  Finishes the destroy if needed.
102  */
103 
ReleaseStrongRefAndUnlockExclusive(IObject * object)104 void ReleaseStrongRefAndUnlockExclusive(IObject *object)
105 {
106 #ifdef USE_DEBUG
107     assert(pthread_equal(pthread_self(), object->mOwner));
108 #endif
109     assert(0 < object->mStrongRefCount);
110     if ((0 == --object->mStrongRefCount) && (SL_OBJECT_STATE_DESTROYING == object->mState)) {
111         // FIXME do the destroy here - merge with IDestroy
112         // but can't do this until we move Destroy to the sync thread
113         // as Destroy is now a blocking operation, and to avoid a race
114     } else {
115         object_unlock_exclusive(object);
116     }
117 }
118 
119 
120 /** \brief Release a strong reference to an object.
121  *  Entry condition: the object is unlocked.
122  *  Exit condition: the object is unlocked.
123  *  Finishes the destroy if needed.
124  */
125 
ReleaseStrongRef(IObject * object)126 void ReleaseStrongRef(IObject *object)
127 {
128     assert(NULL != object);
129     object_lock_exclusive(object);
130     ReleaseStrongRefAndUnlockExclusive(object);
131 }
132 
133 
134 /** \brief Convert POSIX pthread error code to OpenSL ES result code */
135 
err_to_result(int err)136 SLresult err_to_result(int err)
137 {
138     if (EAGAIN == err || ENOMEM == err) {
139         return SL_RESULT_RESOURCE_ERROR;
140     }
141     if (0 != err) {
142         return SL_RESULT_INTERNAL_ERROR;
143     }
144     return SL_RESULT_SUCCESS;
145 }
146 
147 
148 /** \brief Check the interface IDs passed into a Create operation */
149 
checkInterfaces(const ClassTable * clazz,SLuint32 numInterfaces,const SLInterfaceID * pInterfaceIds,const SLboolean * pInterfaceRequired,unsigned * pExposedMask,unsigned * pRequiredMask)150 SLresult checkInterfaces(const ClassTable *clazz, SLuint32 numInterfaces,
151     const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired,
152     unsigned *pExposedMask, unsigned *pRequiredMask)
153 {
154     assert(NULL != clazz && NULL != pExposedMask);
155     // Initially no interfaces are exposed
156     unsigned exposedMask = 0;
157     unsigned requiredMask = 0;
158     const struct iid_vtable *interfaces = clazz->mInterfaces;
159     SLuint32 interfaceCount = clazz->mInterfaceCount;
160     SLuint32 i;
161     // Expose all implicit interfaces
162     for (i = 0; i < interfaceCount; ++i) {
163         switch (interfaces[i].mInterface) {
164         case INTERFACE_IMPLICIT:
165         case INTERFACE_IMPLICIT_PREREALIZE:
166             // there must be an initialization hook present
167             if (NULL != MPH_init_table[interfaces[i].mMPH].mInit) {
168                 exposedMask |= 1 << i;
169             }
170             break;
171         case INTERFACE_EXPLICIT:
172         case INTERFACE_DYNAMIC:
173         case INTERFACE_UNAVAILABLE:
174         case INTERFACE_EXPLICIT_PREREALIZE:
175             break;
176         default:
177             assert(false);
178             break;
179         }
180     }
181     if (0 < numInterfaces) {
182         if (NULL == pInterfaceIds || NULL == pInterfaceRequired) {
183             return SL_RESULT_PARAMETER_INVALID;
184         }
185         bool anyRequiredButUnsupported = false;
186         // Loop for each requested interface
187         for (i = 0; i < numInterfaces; ++i) {
188             SLInterfaceID iid = pInterfaceIds[i];
189             if (NULL == iid) {
190                 return SL_RESULT_PARAMETER_INVALID;
191             }
192             SLboolean isRequired = pInterfaceRequired[i];
193             int MPH, index;
194             if ((0 > (MPH = IID_to_MPH(iid))) ||
195                     // there must be an initialization hook present
196                     (NULL == MPH_init_table[MPH].mInit) ||
197                     (0 > (index = clazz->mMPH_to_index[MPH])) ||
198                     (INTERFACE_UNAVAILABLE == interfaces[index].mInterface)) {
199                 // Here if interface was not found, or is not available for this object type
200                 if (isRequired) {
201                     // Application said it required the interface, so give up
202                     SL_LOGE("class %s interface %u required but unavailable MPH=%d",
203                             clazz->mName, i, MPH);
204                     anyRequiredButUnsupported = true;
205                 }
206                 // Application said it didn't really need the interface, so ignore with warning
207                 SL_LOGW("class %s interface %u requested but unavailable MPH=%d",
208                         clazz->mName, i, MPH);
209                 continue;
210             }
211             if (isRequired) {
212                 requiredMask |= (1 << index);
213             }
214             // The requested interface was both found and available, so expose it
215             exposedMask |= (1 << index);
216             // Note that we ignore duplicate requests, including equal and aliased IDs
217         }
218         if (anyRequiredButUnsupported) {
219             return SL_RESULT_FEATURE_UNSUPPORTED;
220         }
221     }
222     *pExposedMask = exposedMask;
223     if (NULL != pRequiredMask) {
224         *pRequiredMask = requiredMask;
225     }
226     return SL_RESULT_SUCCESS;
227 }
228 
229 
230 /* Interface initialization hooks */
231 
232 extern void
233     I3DCommit_init(void *),
234     I3DDoppler_init(void *),
235     I3DGrouping_init(void *),
236     I3DLocation_init(void *),
237     I3DMacroscopic_init(void *),
238     I3DSource_init(void *),
239     IAndroidConfiguration_init(void *),
240     IAndroidEffect_init(void *),
241     IAndroidEffectCapabilities_init(void *),
242     IAndroidEffectSend_init(void *),
243     IAndroidBufferQueue_init(void *),
244     IAudioDecoderCapabilities_init(void *),
245     IAudioEncoder_init(void *),
246     IAudioEncoderCapabilities_init(void *),
247     IAudioIODeviceCapabilities_init(void *),
248     IBassBoost_init(void *),
249     IBufferQueue_init(void *),
250     IDeviceVolume_init(void *),
251     IDynamicInterfaceManagement_init(void *),
252     IDynamicSource_init(void *),
253     IEffectSend_init(void *),
254     IEngine_init(void *),
255     IEngineCapabilities_init(void *),
256     IEnvironmentalReverb_init(void *),
257     IEqualizer_init(void *),
258     ILEDArray_init(void *),
259     IMIDIMessage_init(void *),
260     IMIDIMuteSolo_init(void *),
261     IMIDITempo_init(void *),
262     IMIDITime_init(void *),
263     IMetadataExtraction_init(void *),
264     IMetadataTraversal_init(void *),
265     IMuteSolo_init(void *),
266     IObject_init(void *),
267     IOutputMix_init(void *),
268     IOutputMixExt_init(void *),
269     IPitch_init(void *),
270     IPlay_init(void *),
271     IPlaybackRate_init(void *),
272     IPrefetchStatus_init(void *),
273     IPresetReverb_init(void *),
274     IRatePitch_init(void *),
275     IRecord_init(void *),
276     ISeek_init(void *),
277     IThreadSync_init(void *),
278     IVibra_init(void *),
279     IVirtualizer_init(void *),
280     IVisualization_init(void *),
281     IVolume_init(void *);
282 
283 extern void
284     I3DGrouping_deinit(void *),
285     IAndroidEffect_deinit(void *),
286     IAndroidEffectCapabilities_deinit(void *),
287     IAndroidBufferQueue_deinit(void *),
288     IBassBoost_deinit(void *),
289     IBufferQueue_deinit(void *),
290     IEngine_deinit(void *),
291     IEnvironmentalReverb_deinit(void *),
292     IEqualizer_deinit(void *),
293     IObject_deinit(void *),
294     IPresetReverb_deinit(void *),
295     IThreadSync_deinit(void *),
296     IVirtualizer_deinit(void *);
297 
298 extern bool
299     IAndroidEffectCapabilities_Expose(void *),
300     IBassBoost_Expose(void *),
301     IEnvironmentalReverb_Expose(void *),
302     IEqualizer_Expose(void *),
303     IPresetReverb_Expose(void *),
304     IVirtualizer_Expose(void *);
305 
306 extern void
307     IXAEngine_init(void *),
308     IStreamInformation_init(void*),
309     IVideoDecoderCapabilities_init(void *);
310 
311 extern void
312     IXAEngine_deinit(void *),
313     IStreamInformation_deinit(void *),
314     IVideoDecoderCapabilities_deinit(void *);
315 
316 extern bool
317     IVideoDecoderCapabilities_expose(void *);
318 
319 #if !(USE_PROFILES & USE_PROFILES_MUSIC)
320 #define IDynamicSource_init         NULL
321 #define IMetadataTraversal_init     NULL
322 #define IVisualization_init         NULL
323 #endif
324 
325 #if !(USE_PROFILES & USE_PROFILES_GAME)
326 #define I3DCommit_init      NULL
327 #define I3DDoppler_init     NULL
328 #define I3DGrouping_init    NULL
329 #define I3DLocation_init    NULL
330 #define I3DMacroscopic_init NULL
331 #define I3DSource_init      NULL
332 #define IMIDIMessage_init   NULL
333 #define IMIDIMuteSolo_init  NULL
334 #define IMIDITempo_init     NULL
335 #define IMIDITime_init      NULL
336 #define IPitch_init         NULL
337 #define IRatePitch_init     NULL
338 #define I3DGrouping_deinit  NULL
339 #endif
340 
341 #if !(USE_PROFILES & USE_PROFILES_BASE)
342 #define IAudioDecoderCapabilities_init   NULL
343 #define IAudioEncoderCapabilities_init   NULL
344 #define IAudioEncoder_init               NULL
345 #define IAudioIODeviceCapabilities_init  NULL
346 #define IDeviceVolume_init               NULL
347 #define IEngineCapabilities_init         NULL
348 #define IThreadSync_init                 NULL
349 #define IThreadSync_deinit               NULL
350 #endif
351 
352 #if !(USE_PROFILES & USE_PROFILES_OPTIONAL)
353 #define ILEDArray_init  NULL
354 #define IVibra_init     NULL
355 #endif
356 
357 #ifndef ANDROID
358 #define IAndroidConfiguration_init        NULL
359 #define IAndroidEffect_init               NULL
360 #define IAndroidEffectCapabilities_init   NULL
361 #define IAndroidEffectSend_init           NULL
362 #define IAndroidEffect_deinit             NULL
363 #define IAndroidEffectCapabilities_deinit NULL
364 #define IAndroidEffectCapabilities_Expose NULL
365 #define IAndroidBufferQueue_init          NULL
366 #define IStreamInformation_init           NULL
367 #define IAndroidBufferQueue_deinit        NULL
368 #define IStreamInformation_deinit         NULL
369 #endif
370 
371 #ifndef USE_OUTPUTMIXEXT
372 #define IOutputMixExt_init  NULL
373 #endif
374 
375 
376 /*static*/ const struct MPH_init MPH_init_table[MPH_MAX] = {
377     { /* MPH_3DCOMMIT, */ I3DCommit_init, NULL, NULL, NULL, NULL },
378     { /* MPH_3DDOPPLER, */ I3DDoppler_init, NULL, NULL, NULL, NULL },
379     { /* MPH_3DGROUPING, */ I3DGrouping_init, NULL, I3DGrouping_deinit, NULL, NULL },
380     { /* MPH_3DLOCATION, */ I3DLocation_init, NULL, NULL, NULL, NULL },
381     { /* MPH_3DMACROSCOPIC, */ I3DMacroscopic_init, NULL, NULL, NULL, NULL },
382     { /* MPH_3DSOURCE, */ I3DSource_init, NULL, NULL, NULL, NULL },
383     { /* MPH_AUDIODECODERCAPABILITIES, */ IAudioDecoderCapabilities_init, NULL, NULL, NULL, NULL },
384     { /* MPH_AUDIOENCODER, */ IAudioEncoder_init, NULL, NULL, NULL, NULL },
385     { /* MPH_AUDIOENCODERCAPABILITIES, */ IAudioEncoderCapabilities_init, NULL, NULL, NULL, NULL },
386     { /* MPH_AUDIOIODEVICECAPABILITIES, */ IAudioIODeviceCapabilities_init, NULL, NULL, NULL,
387         NULL },
388     { /* MPH_BASSBOOST, */ IBassBoost_init, NULL, IBassBoost_deinit, IBassBoost_Expose, NULL },
389     { /* MPH_BUFFERQUEUE, */ IBufferQueue_init, NULL, IBufferQueue_deinit, NULL, NULL },
390     { /* MPH_DEVICEVOLUME, */ IDeviceVolume_init, NULL, NULL, NULL, NULL },
391     { /* MPH_DYNAMICINTERFACEMANAGEMENT, */ IDynamicInterfaceManagement_init, NULL, NULL, NULL,
392         NULL },
393     { /* MPH_DYNAMICSOURCE, */ IDynamicSource_init, NULL, NULL, NULL, NULL },
394     { /* MPH_EFFECTSEND, */ IEffectSend_init, NULL, NULL, NULL, NULL },
395     { /* MPH_ENGINE, */ IEngine_init, NULL, IEngine_deinit, NULL, NULL },
396     { /* MPH_ENGINECAPABILITIES, */ IEngineCapabilities_init, NULL, NULL, NULL, NULL },
397     { /* MPH_ENVIRONMENTALREVERB, */ IEnvironmentalReverb_init, NULL, IEnvironmentalReverb_deinit,
398         IEnvironmentalReverb_Expose, NULL },
399     { /* MPH_EQUALIZER, */ IEqualizer_init, NULL, IEqualizer_deinit, IEqualizer_Expose, NULL },
400     { /* MPH_LED, */ ILEDArray_init, NULL, NULL, NULL, NULL },
401     { /* MPH_METADATAEXTRACTION, */ IMetadataExtraction_init, NULL, NULL, NULL, NULL },
402     { /* MPH_METADATATRAVERSAL, */ IMetadataTraversal_init, NULL, NULL, NULL, NULL },
403     { /* MPH_MIDIMESSAGE, */ IMIDIMessage_init, NULL, NULL, NULL, NULL },
404     { /* MPH_MIDITIME, */ IMIDITime_init, NULL, NULL, NULL, NULL },
405     { /* MPH_MIDITEMPO, */ IMIDITempo_init, NULL, NULL, NULL, NULL },
406     { /* MPH_MIDIMUTESOLO, */ IMIDIMuteSolo_init, NULL, NULL, NULL, NULL },
407     { /* MPH_MUTESOLO, */ IMuteSolo_init, NULL, NULL, NULL, NULL },
408     { /* MPH_NULL, */ NULL, NULL, NULL, NULL, NULL },
409     { /* MPH_OBJECT, */ IObject_init, NULL, IObject_deinit, NULL, NULL },
410     { /* MPH_OUTPUTMIX, */ IOutputMix_init, NULL, NULL, NULL, NULL },
411     { /* MPH_PITCH, */ IPitch_init, NULL, NULL, NULL, NULL },
412     { /* MPH_PLAY, */ IPlay_init, NULL, NULL, NULL, NULL },
413     { /* MPH_PLAYBACKRATE, */ IPlaybackRate_init, NULL, NULL, NULL, NULL },
414     { /* MPH_PREFETCHSTATUS, */ IPrefetchStatus_init, NULL, NULL, NULL, NULL },
415     { /* MPH_PRESETREVERB, */ IPresetReverb_init, NULL, IPresetReverb_deinit,
416         IPresetReverb_Expose, NULL },
417     { /* MPH_RATEPITCH, */ IRatePitch_init, NULL, NULL, NULL, NULL },
418     { /* MPH_RECORD, */ IRecord_init, NULL, NULL, NULL, NULL },
419     { /* MPH_SEEK, */ ISeek_init, NULL, NULL, NULL, NULL },
420     { /* MPH_THREADSYNC, */ IThreadSync_init, NULL, IThreadSync_deinit, NULL, NULL },
421     { /* MPH_VIBRA, */ IVibra_init, NULL, NULL, NULL, NULL },
422     { /* MPH_VIRTUALIZER, */ IVirtualizer_init, NULL, IVirtualizer_deinit, IVirtualizer_Expose,
423         NULL },
424     { /* MPH_VISUALIZATION, */ IVisualization_init, NULL, NULL, NULL, NULL },
425     { /* MPH_VOLUME, */ IVolume_init, NULL, NULL, NULL, NULL },
426 // Wilhelm desktop extended interfaces
427     { /* MPH_OUTPUTMIXEXT, */ IOutputMixExt_init, NULL, NULL, NULL, NULL },
428 // Android API level 9 extended interfaces
429     { /* MPH_ANDROIDEFFECT */ IAndroidEffect_init, NULL, IAndroidEffect_deinit, NULL, NULL },
430     { /* MPH_ANDROIDEFFECTCAPABILITIES */ IAndroidEffectCapabilities_init, NULL,
431         IAndroidEffectCapabilities_deinit, IAndroidEffectCapabilities_Expose, NULL },
432     { /* MPH_ANDROIDEFFECTSEND */ IAndroidEffectSend_init, NULL, NULL, NULL, NULL },
433     { /* MPH_ANDROIDCONFIGURATION */ IAndroidConfiguration_init, NULL, NULL, NULL, NULL },
434     { /* MPH_ANDROIDSIMPLEBUFFERQUEUE */ IBufferQueue_init /* alias */, NULL, NULL, NULL, NULL },
435 // Android API level 10 extended interfaces
436     { /* MPH_ANDROIDBUFFERQUEUESOURCE */ IAndroidBufferQueue_init, NULL, IAndroidBufferQueue_deinit,
437         NULL, NULL },
438 // OpenMAX AL 1.0.1 interfaces
439     { /* MPH_XAAUDIODECODERCAPABILITIES */ NULL, NULL, NULL, NULL, NULL },
440     { /* MPH_XAAUDIOENCODER */ NULL, NULL, NULL, NULL, NULL },
441     { /* MPH_XAAUDIOENCODERCAPABILITIES */ NULL, NULL, NULL, NULL, NULL },
442     { /* MPH_XAAUDIOIODEVICECAPABILITIES */ NULL, NULL, NULL, NULL, NULL },
443     { /* MPH_XACAMERA */ NULL, NULL, NULL, NULL, NULL },
444     { /* MPH_XACAMERACAPABILITIES */ NULL, NULL, NULL, NULL, NULL },
445     { /* MPH_XACONFIGEXTENSION */ NULL, NULL, NULL, NULL, NULL },
446     { /* MPH_XADEVICEVOLUME */ NULL, NULL, NULL, NULL, NULL },
447     { /* MPH_XADYNAMICINTERFACEMANAGEMENT 59 */ NULL, NULL, NULL, NULL, NULL },
448     { /* MPH_XADYNAMICSOURCE */ NULL, NULL, NULL, NULL, NULL },
449     { /* MPH_XAENGINE */ IXAEngine_init, NULL, IXAEngine_deinit, NULL, NULL },
450     { /* MPH_XAEQUALIZER */ NULL, NULL, NULL, NULL, NULL },
451     { /* MPH_XAIMAGECONTROLS */ NULL, NULL, NULL, NULL, NULL },
452     { /* MPH_XAIMAGEDECODERCAPABILITIES */ NULL, NULL, NULL, NULL, NULL },
453     { /* MPH_XAIMAGEEFFECTS */ NULL, NULL, NULL, NULL, NULL },
454     { /* MPH_XAIMAGEENCODER */ NULL, NULL, NULL, NULL, NULL },
455     { /* MPH_XAIMAGEENCODERCAPABILITIES */ NULL, NULL, NULL, NULL, NULL },
456     { /* MPH_XALED */ NULL, NULL, NULL, NULL, NULL },
457     { /* MPH_XAMETADATAEXTRACTION */ NULL, NULL, NULL, NULL, NULL },
458     { /* MPH_XAMETADATAINSERTION */ NULL, NULL, NULL, NULL, NULL },
459     { /* MPH_XAMETADATATRAVERSAL */ NULL, NULL, NULL, NULL, NULL },
460 //  { /* MPH_XANULL */ NULL, NULL, NULL, NULL, NULL },
461     { /* MPH_XAOBJECT */ IObject_init, NULL, IObject_deinit, NULL, NULL },
462     { /* MPH_XAOUTPUTMIX */ NULL, NULL, NULL, NULL, NULL },
463     { /* MPH_XAPLAY */ IPlay_init, NULL, NULL, NULL, NULL },
464     { /* MPH_XAPLAYBACKRATE */ NULL, NULL, NULL, NULL, NULL },
465     { /* MPH_XAPREFETCHSTATUS, */ IPrefetchStatus_init, NULL, NULL, NULL, NULL },
466     { /* MPH_XARADIO */ NULL, NULL, NULL, NULL, NULL },
467     { /* MPH_XARDS */ NULL, NULL, NULL, NULL, NULL },
468     { /* MPH_XARECORD */ NULL, NULL, NULL, NULL, NULL },
469     { /* MPH_XASEEK */ ISeek_init, NULL, NULL, NULL, NULL },
470     { /* MPH_XASNAPSHOT */ NULL, NULL, NULL, NULL, NULL },
471     { /* MPH_XASTREAMINFORMATION */ IStreamInformation_init, NULL, IStreamInformation_deinit,
472         NULL, NULL },
473     { /* MPH_XATHREADSYNC */ NULL, NULL, NULL, NULL, NULL },
474     { /* MPH_XAVIBRA */ NULL, NULL, NULL, NULL, NULL },
475     { /* MPH_XAVIDEODECODERCAPABILITIES */ IVideoDecoderCapabilities_init, NULL,
476             IVideoDecoderCapabilities_deinit, IVideoDecoderCapabilities_expose, NULL },
477     { /* MPH_XAVIDEOENCODER */ NULL, NULL, NULL, NULL, NULL },
478     { /* MPH_XAVIDEOENCODERCAPABILITIES */ NULL, NULL, NULL, NULL, NULL },
479     { /* MPH_XAVIDEOPOSTPROCESSING */ NULL, NULL, NULL, NULL, NULL },
480     { /* MPH_XAVOLUME, */ IVolume_init, NULL, NULL, NULL, NULL },
481 };
482 
483 
484 /** \brief Construct a new instance of the specified class, exposing selected interfaces */
485 
construct(const ClassTable * clazz,unsigned exposedMask,SLEngineItf engine)486 IObject *construct(const ClassTable *clazz, unsigned exposedMask, SLEngineItf engine)
487 {
488     IObject *thiz;
489     // Do not change this to malloc; we depend on the object being memset to zero
490     thiz = (IObject *) calloc(1, clazz->mSize);
491     if (NULL != thiz) {
492         SL_LOGV("construct %s at %p", clazz->mName, thiz);
493         unsigned lossOfControlMask = 0;
494         // a NULL engine means we are constructing the engine
495         IEngine *thisEngine = (IEngine *) engine;
496         if (NULL == thisEngine) {
497             // thisEngine = &((CEngine *) thiz)->mEngine;
498             thiz->mEngine = (CEngine *) thiz;
499         } else {
500             thiz->mEngine = (CEngine *) thisEngine->mThis;
501             interface_lock_exclusive(thisEngine);
502             if (MAX_INSTANCE <= thisEngine->mInstanceCount) {
503                 SL_LOGE("Too many objects");
504                 interface_unlock_exclusive(thisEngine);
505                 free(thiz);
506                 return NULL;
507             }
508             // pre-allocate a pending slot, but don't assign bit from mInstanceMask yet
509             ++thisEngine->mInstanceCount;
510             assert(((unsigned) ~0) != thisEngine->mInstanceMask);
511             interface_unlock_exclusive(thisEngine);
512             // const, no lock needed
513             if (thisEngine->mLossOfControlGlobal) {
514                 lossOfControlMask = ~0;
515             }
516         }
517         thiz->mLossOfControlMask = lossOfControlMask;
518         thiz->mClass = clazz;
519         const struct iid_vtable *x = clazz->mInterfaces;
520         SLuint8 *interfaceStateP = thiz->mInterfaceStates;
521         SLuint32 index;
522         for (index = 0; index < clazz->mInterfaceCount; ++index, ++x, exposedMask >>= 1) {
523             SLuint8 state;
524             // initialize all interfaces with init hooks, even if not exposed
525             const struct MPH_init *mi = &MPH_init_table[x->mMPH];
526             VoidHook init = mi->mInit;
527             if (NULL != init) {
528                 void *self = (char *) thiz + x->mOffset;
529                 // IObject does not have an mThis, so [1] is not always defined
530                 if (index) {
531                     ((IObject **) self)[1] = thiz;
532                 }
533                 // call the initialization hook
534                 (*init)(self);
535                 // IObject does not require a call to GetInterface
536                 if (index) {
537                     // This trickery invalidates the v-table until GetInterface
538                     ((size_t *) self)[0] ^= ~0;
539                 }
540                 // if interface is exposed, also call the optional expose hook
541                 BoolHook expose;
542                 state = (exposedMask & 1) && ((NULL == (expose = mi->mExpose)) || (*expose)(self)) ?
543                         INTERFACE_EXPOSED : INTERFACE_INITIALIZED;
544                 // FIXME log or report to application if an expose hook on a
545                 // required explicit interface fails at creation time
546             } else {
547                 state = INTERFACE_UNINITIALIZED;
548             }
549             *interfaceStateP++ = state;
550         }
551         // note that the new object is not yet published; creator must call IObject_Publish
552     }
553     return thiz;
554 }
555