| /* | |
| * Copyright (C) 2010 The Android Open Source Project | |
| * | |
| * Licensed under the Apache License, Version 2.0 (the "License"); | |
| * you may not use this file except in compliance with the License. | |
| * You may obtain a copy of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, software | |
| * distributed under the License is distributed on an "AS IS" BASIS, | |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| * See the License for the specific language governing permissions and | |
| * limitations under the License. | |
| */ | |
| /* OpenSL ES private and global functions not associated with an interface or class */ | |
| #include "sles_allinclusive.h" | |
| /** \brief Return true if the specified interface exists and has been initialized for this object. | |
| * Returns false if the class does not support this kind of interface, or the class supports the | |
| * interface but this particular object has not had the interface exposed at object creation time | |
| * or by DynamicInterface::AddInterface. Note that the return value is not affected by whether | |
| * the application has requested access to the interface with Object::GetInterface. Assumes on | |
| * entry that the object is locked for either shared or exclusive access. | |
| */ | |
| bool IsInterfaceInitialized(IObject *thiz, unsigned MPH) | |
| { | |
| assert(NULL != thiz); | |
| assert( /* (MPH_MIN <= MPH) && */ (MPH < (unsigned) MPH_MAX)); | |
| const ClassTable *clazz = thiz->mClass; | |
| assert(NULL != clazz); | |
| int index; | |
| if (0 > (index = clazz->mMPH_to_index[MPH])) { | |
| return false; | |
| } | |
| assert(SLES_MAX_INDEX >= clazz->mInterfaceCount); | |
| assert(clazz->mInterfaceCount > (unsigned) index); | |
| switch (thiz->mInterfaceStates[index]) { | |
| case INTERFACE_EXPOSED: | |
| case INTERFACE_ADDED: | |
| return true; | |
| default: | |
| return false; | |
| } | |
| } | |
| /** \brief Map an IObject to it's "object ID" (which is really a class ID) */ | |
| SLuint32 IObjectToObjectID(IObject *thiz) | |
| { | |
| assert(NULL != thiz); | |
| // Note this returns the OpenSL ES object ID in preference to the OpenMAX AL if both available | |
| const ClassTable *clazz = thiz->mClass; | |
| assert(NULL != clazz); | |
| SLuint32 id = clazz->mSLObjectID; | |
| if (!id) { | |
| id = clazz->mXAObjectID; | |
| } | |
| return id; | |
| } | |
| /** \brief Acquire a strong reference to an object. | |
| * Check that object has the specified "object ID" (which is really a class ID) and is in the | |
| * realized state. If so, then acquire a strong reference to it and return true. | |
| * Otherwise return false. | |
| */ | |
| SLresult AcquireStrongRef(IObject *object, SLuint32 expectedObjectID) | |
| { | |
| if (NULL == object) { | |
| return SL_RESULT_PARAMETER_INVALID; | |
| } | |
| // NTH additional validity checks on address here | |
| SLresult result; | |
| object_lock_exclusive(object); | |
| SLuint32 actualObjectID = IObjectToObjectID(object); | |
| if (expectedObjectID != actualObjectID) { | |
| SL_LOGE("object %p has object ID %u but expected %u", object, actualObjectID, | |
| expectedObjectID); | |
| result = SL_RESULT_PARAMETER_INVALID; | |
| } else if (SL_OBJECT_STATE_REALIZED != object->mState) { | |
| SL_LOGE("object %p with object ID %u is not realized", object, actualObjectID); | |
| result = SL_RESULT_PRECONDITIONS_VIOLATED; | |
| } else { | |
| ++object->mStrongRefCount; | |
| result = SL_RESULT_SUCCESS; | |
| } | |
| object_unlock_exclusive(object); | |
| return result; | |
| } | |
| /** \brief Release a strong reference to an object. | |
| * Entry condition: the object is locked. | |
| * Exit condition: the object is unlocked. | |
| * Finishes the destroy if needed. | |
| */ | |
| void ReleaseStrongRefAndUnlockExclusive(IObject *object) | |
| { | |
| #ifdef USE_DEBUG | |
| assert(pthread_equal(pthread_self(), object->mOwner)); | |
| #endif | |
| assert(0 < object->mStrongRefCount); | |
| if ((0 == --object->mStrongRefCount) && (SL_OBJECT_STATE_DESTROYING == object->mState)) { | |
| // FIXME do the destroy here - merge with IDestroy | |
| // but can't do this until we move Destroy to the sync thread | |
| // as Destroy is now a blocking operation, and to avoid a race | |
| } else { | |
| object_unlock_exclusive(object); | |
| } | |
| } | |
| /** \brief Release a strong reference to an object. | |
| * Entry condition: the object is unlocked. | |
| * Exit condition: the object is unlocked. | |
| * Finishes the destroy if needed. | |
| */ | |
| void ReleaseStrongRef(IObject *object) | |
| { | |
| assert(NULL != object); | |
| object_lock_exclusive(object); | |
| ReleaseStrongRefAndUnlockExclusive(object); | |
| } | |
| /** \brief Convert POSIX pthread error code to OpenSL ES result code */ | |
| SLresult err_to_result(int err) | |
| { | |
| if (EAGAIN == err || ENOMEM == err) { | |
| return SL_RESULT_RESOURCE_ERROR; | |
| } | |
| if (0 != err) { | |
| return SL_RESULT_INTERNAL_ERROR; | |
| } | |
| return SL_RESULT_SUCCESS; | |
| } | |
| /** \brief Check the interface IDs passed into a Create operation */ | |
| SLresult checkInterfaces(const ClassTable *clazz, SLuint32 numInterfaces, | |
| const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired, | |
| unsigned *pExposedMask, unsigned *pRequiredMask) | |
| { | |
| assert(NULL != clazz && NULL != pExposedMask); | |
| // Initially no interfaces are exposed | |
| unsigned exposedMask = 0; | |
| unsigned requiredMask = 0; | |
| const struct iid_vtable *interfaces = clazz->mInterfaces; | |
| SLuint32 interfaceCount = clazz->mInterfaceCount; | |
| SLuint32 i; | |
| // Expose all implicit interfaces | |
| for (i = 0; i < interfaceCount; ++i) { | |
| switch (interfaces[i].mInterface) { | |
| case INTERFACE_IMPLICIT: | |
| case INTERFACE_IMPLICIT_PREREALIZE: | |
| // there must be an initialization hook present | |
| if (NULL != MPH_init_table[interfaces[i].mMPH].mInit) { | |
| exposedMask |= 1 << i; | |
| } | |
| break; | |
| case INTERFACE_EXPLICIT: | |
| case INTERFACE_DYNAMIC: | |
| case INTERFACE_UNAVAILABLE: | |
| case INTERFACE_EXPLICIT_PREREALIZE: | |
| break; | |
| default: | |
| assert(false); | |
| break; | |
| } | |
| } | |
| if (0 < numInterfaces) { | |
| if (NULL == pInterfaceIds || NULL == pInterfaceRequired) { | |
| return SL_RESULT_PARAMETER_INVALID; | |
| } | |
| bool anyRequiredButUnsupported = false; | |
| // Loop for each requested interface | |
| for (i = 0; i < numInterfaces; ++i) { | |
| SLInterfaceID iid = pInterfaceIds[i]; | |
| if (NULL == iid) { | |
| return SL_RESULT_PARAMETER_INVALID; | |
| } | |
| SLboolean isRequired = pInterfaceRequired[i]; | |
| int MPH, index; | |
| if ((0 > (MPH = IID_to_MPH(iid))) || | |
| // there must be an initialization hook present | |
| (NULL == MPH_init_table[MPH].mInit) || | |
| (0 > (index = clazz->mMPH_to_index[MPH])) || | |
| (INTERFACE_UNAVAILABLE == interfaces[index].mInterface)) { | |
| // Here if interface was not found, or is not available for this object type | |
| if (isRequired) { | |
| // Application said it required the interface, so give up | |
| SL_LOGE("class %s interface %u required but unavailable MPH=%d", | |
| clazz->mName, i, MPH); | |
| anyRequiredButUnsupported = true; | |
| } | |
| // Application said it didn't really need the interface, so ignore with warning | |
| SL_LOGW("class %s interface %u requested but unavailable MPH=%d", | |
| clazz->mName, i, MPH); | |
| continue; | |
| } | |
| if (isRequired) { | |
| requiredMask |= (1 << index); | |
| } | |
| // The requested interface was both found and available, so expose it | |
| exposedMask |= (1 << index); | |
| // Note that we ignore duplicate requests, including equal and aliased IDs | |
| } | |
| if (anyRequiredButUnsupported) { | |
| return SL_RESULT_FEATURE_UNSUPPORTED; | |
| } | |
| } | |
| *pExposedMask = exposedMask; | |
| if (NULL != pRequiredMask) { | |
| *pRequiredMask = requiredMask; | |
| } | |
| return SL_RESULT_SUCCESS; | |
| } | |
| /* Interface initialization hooks */ | |
| extern void | |
| I3DCommit_init(void *), | |
| I3DDoppler_init(void *), | |
| I3DGrouping_init(void *), | |
| I3DLocation_init(void *), | |
| I3DMacroscopic_init(void *), | |
| I3DSource_init(void *), | |
| IAndroidAcousticEchoCancellation_init(void *), | |
| IAndroidAutomaticGainControl_init(void *), | |
| IAndroidConfiguration_init(void *), | |
| IAndroidEffect_init(void *), | |
| IAndroidEffectCapabilities_init(void *), | |
| IAndroidEffectSend_init(void *), | |
| IAndroidBufferQueue_init(void *), | |
| IAudioDecoderCapabilities_init(void *), | |
| IAudioEncoder_init(void *), | |
| IAudioEncoderCapabilities_init(void *), | |
| IAudioIODeviceCapabilities_init(void *), | |
| IBassBoost_init(void *), | |
| IBufferQueue_init(void *), | |
| IDeviceVolume_init(void *), | |
| IDynamicInterfaceManagement_init(void *), | |
| IDynamicSource_init(void *), | |
| IEffectSend_init(void *), | |
| IEngine_init(void *), | |
| IEngineCapabilities_init(void *), | |
| IEnvironmentalReverb_init(void *), | |
| IEqualizer_init(void *), | |
| ILEDArray_init(void *), | |
| IMIDIMessage_init(void *), | |
| IMIDIMuteSolo_init(void *), | |
| IMIDITempo_init(void *), | |
| IMIDITime_init(void *), | |
| IMetadataExtraction_init(void *), | |
| IMetadataTraversal_init(void *), | |
| IMuteSolo_init(void *), | |
| IAndroidNoiseSuppression_init(void *), | |
| IObject_init(void *), | |
| IOutputMix_init(void *), | |
| IOutputMixExt_init(void *), | |
| IPitch_init(void *), | |
| IPlay_init(void *), | |
| IPlaybackRate_init(void *), | |
| IPrefetchStatus_init(void *), | |
| IPresetReverb_init(void *), | |
| IRatePitch_init(void *), | |
| IRecord_init(void *), | |
| ISeek_init(void *), | |
| IThreadSync_init(void *), | |
| IVibra_init(void *), | |
| IVirtualizer_init(void *), | |
| IVisualization_init(void *), | |
| IVolume_init(void *); | |
| extern void | |
| I3DGrouping_deinit(void *), | |
| IAndroidAcousticEchoCancellation_deinit(void *), | |
| IAndroidAutomaticGainControl_deinit(void *), | |
| IAndroidEffect_deinit(void *), | |
| IAndroidEffectCapabilities_deinit(void *), | |
| IAndroidBufferQueue_deinit(void *), | |
| IAndroidNoiseSuppression_deinit(void*), | |
| IBassBoost_deinit(void *), | |
| IBufferQueue_deinit(void *), | |
| IEngine_deinit(void *), | |
| IEnvironmentalReverb_deinit(void *), | |
| IEqualizer_deinit(void *), | |
| IObject_deinit(void *), | |
| IPresetReverb_deinit(void *), | |
| IThreadSync_deinit(void *), | |
| IVirtualizer_deinit(void *), | |
| IAndroidConfiguration_deinit(void *); | |
| extern bool | |
| IAndroidAcousticEchoCancellation_Expose(void *), | |
| IAndroidAutomaticGainControl_Expose(void *), | |
| IAndroidEffectCapabilities_Expose(void *), | |
| IAndroidNoiseSuppression_Expose(void *), | |
| IBassBoost_Expose(void *), | |
| IEnvironmentalReverb_Expose(void *), | |
| IEqualizer_Expose(void *), | |
| IPresetReverb_Expose(void *), | |
| IVirtualizer_Expose(void *); | |
| extern void | |
| IXAEngine_init(void *), | |
| IStreamInformation_init(void*), | |
| IVideoDecoderCapabilities_init(void *); | |
| extern void | |
| IXAEngine_deinit(void *), | |
| IStreamInformation_deinit(void *), | |
| IVideoDecoderCapabilities_deinit(void *); | |
| extern bool | |
| IVideoDecoderCapabilities_expose(void *); | |
| #if !(USE_PROFILES & USE_PROFILES_MUSIC) | |
| #define IDynamicSource_init NULL | |
| #define IMetadataTraversal_init NULL | |
| #define IVisualization_init NULL | |
| #endif | |
| #if !(USE_PROFILES & USE_PROFILES_GAME) | |
| #define I3DCommit_init NULL | |
| #define I3DDoppler_init NULL | |
| #define I3DGrouping_init NULL | |
| #define I3DLocation_init NULL | |
| #define I3DMacroscopic_init NULL | |
| #define I3DSource_init NULL | |
| #define IMIDIMessage_init NULL | |
| #define IMIDIMuteSolo_init NULL | |
| #define IMIDITempo_init NULL | |
| #define IMIDITime_init NULL | |
| #define IPitch_init NULL | |
| #define IRatePitch_init NULL | |
| #define I3DGrouping_deinit NULL | |
| #endif | |
| #if !(USE_PROFILES & USE_PROFILES_BASE) | |
| #define IAudioDecoderCapabilities_init NULL | |
| #define IAudioEncoderCapabilities_init NULL | |
| #define IAudioEncoder_init NULL | |
| #define IAudioIODeviceCapabilities_init NULL | |
| #define IDeviceVolume_init NULL | |
| #define IEngineCapabilities_init NULL | |
| #define IThreadSync_init NULL | |
| #define IThreadSync_deinit NULL | |
| #endif | |
| #if !(USE_PROFILES & USE_PROFILES_OPTIONAL) | |
| #define ILEDArray_init NULL | |
| #define IVibra_init NULL | |
| #endif | |
| #ifndef ANDROID | |
| #define IAndroidConfiguration_init NULL | |
| #define IAndroidConfiguration_deinit NULL | |
| #define IAndroidEffect_init NULL | |
| #define IAndroidEffectCapabilities_init NULL | |
| #define IAndroidEffectSend_init NULL | |
| #define IAndroidEffect_deinit NULL | |
| #define IAndroidEffectCapabilities_deinit NULL | |
| #define IAndroidEffectCapabilities_Expose NULL | |
| #define IAndroidBufferQueue_init NULL | |
| #define IStreamInformation_init NULL | |
| #define IAndroidBufferQueue_deinit NULL | |
| #define IStreamInformation_deinit NULL | |
| #endif | |
| #ifndef USE_OUTPUTMIXEXT | |
| #define IOutputMixExt_init NULL | |
| #endif | |
| /*static*/ const struct MPH_init MPH_init_table[MPH_MAX] = { | |
| { /* MPH_3DCOMMIT, */ I3DCommit_init, NULL, NULL, NULL, NULL }, | |
| { /* MPH_3DDOPPLER, */ I3DDoppler_init, NULL, NULL, NULL, NULL }, | |
| { /* MPH_3DGROUPING, */ I3DGrouping_init, NULL, I3DGrouping_deinit, NULL, NULL }, | |
| { /* MPH_3DLOCATION, */ I3DLocation_init, NULL, NULL, NULL, NULL }, | |
| { /* MPH_3DMACROSCOPIC, */ I3DMacroscopic_init, NULL, NULL, NULL, NULL }, | |
| { /* MPH_3DSOURCE, */ I3DSource_init, NULL, NULL, NULL, NULL }, | |
| { /* MPH_AUDIODECODERCAPABILITIES, */ IAudioDecoderCapabilities_init, NULL, NULL, NULL, NULL }, | |
| { /* MPH_AUDIOENCODER, */ IAudioEncoder_init, NULL, NULL, NULL, NULL }, | |
| { /* MPH_AUDIOENCODERCAPABILITIES, */ IAudioEncoderCapabilities_init, NULL, NULL, NULL, NULL }, | |
| { /* MPH_AUDIOIODEVICECAPABILITIES, */ IAudioIODeviceCapabilities_init, NULL, NULL, NULL, | |
| NULL }, | |
| { /* MPH_BASSBOOST, */ IBassBoost_init, NULL, IBassBoost_deinit, IBassBoost_Expose, NULL }, | |
| { /* MPH_BUFFERQUEUE, */ IBufferQueue_init, NULL, IBufferQueue_deinit, NULL, NULL }, | |
| { /* MPH_DEVICEVOLUME, */ IDeviceVolume_init, NULL, NULL, NULL, NULL }, | |
| { /* MPH_DYNAMICINTERFACEMANAGEMENT, */ IDynamicInterfaceManagement_init, NULL, NULL, NULL, | |
| NULL }, | |
| { /* MPH_DYNAMICSOURCE, */ IDynamicSource_init, NULL, NULL, NULL, NULL }, | |
| { /* MPH_EFFECTSEND, */ IEffectSend_init, NULL, NULL, NULL, NULL }, | |
| { /* MPH_ENGINE, */ IEngine_init, NULL, IEngine_deinit, NULL, NULL }, | |
| { /* MPH_ENGINECAPABILITIES, */ IEngineCapabilities_init, NULL, NULL, NULL, NULL }, | |
| { /* MPH_ENVIRONMENTALREVERB, */ IEnvironmentalReverb_init, NULL, IEnvironmentalReverb_deinit, | |
| IEnvironmentalReverb_Expose, NULL }, | |
| { /* MPH_EQUALIZER, */ IEqualizer_init, NULL, IEqualizer_deinit, IEqualizer_Expose, NULL }, | |
| { /* MPH_LED, */ ILEDArray_init, NULL, NULL, NULL, NULL }, | |
| { /* MPH_METADATAEXTRACTION, */ IMetadataExtraction_init, NULL, NULL, NULL, NULL }, | |
| { /* MPH_METADATATRAVERSAL, */ IMetadataTraversal_init, NULL, NULL, NULL, NULL }, | |
| { /* MPH_MIDIMESSAGE, */ IMIDIMessage_init, NULL, NULL, NULL, NULL }, | |
| { /* MPH_MIDITIME, */ IMIDITime_init, NULL, NULL, NULL, NULL }, | |
| { /* MPH_MIDITEMPO, */ IMIDITempo_init, NULL, NULL, NULL, NULL }, | |
| { /* MPH_MIDIMUTESOLO, */ IMIDIMuteSolo_init, NULL, NULL, NULL, NULL }, | |
| { /* MPH_MUTESOLO, */ IMuteSolo_init, NULL, NULL, NULL, NULL }, | |
| { /* MPH_NULL, */ NULL, NULL, NULL, NULL, NULL }, | |
| { /* MPH_OBJECT, */ IObject_init, NULL, IObject_deinit, NULL, NULL }, | |
| { /* MPH_OUTPUTMIX, */ IOutputMix_init, NULL, NULL, NULL, NULL }, | |
| { /* MPH_PITCH, */ IPitch_init, NULL, NULL, NULL, NULL }, | |
| { /* MPH_PLAY, */ IPlay_init, NULL, NULL, NULL, NULL }, | |
| { /* MPH_PLAYBACKRATE, */ IPlaybackRate_init, NULL, NULL, NULL, NULL }, | |
| { /* MPH_PREFETCHSTATUS, */ IPrefetchStatus_init, NULL, NULL, NULL, NULL }, | |
| { /* MPH_PRESETREVERB, */ IPresetReverb_init, NULL, IPresetReverb_deinit, | |
| IPresetReverb_Expose, NULL }, | |
| { /* MPH_RATEPITCH, */ IRatePitch_init, NULL, NULL, NULL, NULL }, | |
| { /* MPH_RECORD, */ IRecord_init, NULL, NULL, NULL, NULL }, | |
| { /* MPH_SEEK, */ ISeek_init, NULL, NULL, NULL, NULL }, | |
| { /* MPH_THREADSYNC, */ IThreadSync_init, NULL, IThreadSync_deinit, NULL, NULL }, | |
| { /* MPH_VIBRA, */ IVibra_init, NULL, NULL, NULL, NULL }, | |
| { /* MPH_VIRTUALIZER, */ IVirtualizer_init, NULL, IVirtualizer_deinit, IVirtualizer_Expose, | |
| NULL }, | |
| { /* MPH_VISUALIZATION, */ IVisualization_init, NULL, NULL, NULL, NULL }, | |
| { /* MPH_VOLUME, */ IVolume_init, NULL, NULL, NULL, NULL }, | |
| // Wilhelm desktop extended interfaces | |
| { /* MPH_OUTPUTMIXEXT, */ IOutputMixExt_init, NULL, NULL, NULL, NULL }, | |
| // Android API level 9 extended interfaces | |
| { /* MPH_ANDROIDEFFECT */ IAndroidEffect_init, NULL, IAndroidEffect_deinit, NULL, NULL }, | |
| { /* MPH_ANDROIDEFFECTCAPABILITIES */ IAndroidEffectCapabilities_init, NULL, | |
| IAndroidEffectCapabilities_deinit, IAndroidEffectCapabilities_Expose, NULL }, | |
| { /* MPH_ANDROIDEFFECTSEND */ IAndroidEffectSend_init, NULL, NULL, NULL, NULL }, | |
| { /* MPH_ANDROIDCONFIGURATION */ IAndroidConfiguration_init, NULL, IAndroidConfiguration_deinit, | |
| NULL, NULL }, | |
| { /* MPH_ANDROIDSIMPLEBUFFERQUEUE */ IBufferQueue_init /* alias */, NULL, NULL, NULL, NULL }, | |
| // Android API level 10 extended interfaces | |
| { /* MPH_ANDROIDBUFFERQUEUESOURCE */ IAndroidBufferQueue_init, NULL, IAndroidBufferQueue_deinit, | |
| NULL, NULL }, | |
| // OpenMAX AL 1.0.1 interfaces | |
| { /* MPH_XAAUDIODECODERCAPABILITIES */ NULL, NULL, NULL, NULL, NULL }, | |
| { /* MPH_XAAUDIOENCODER */ NULL, NULL, NULL, NULL, NULL }, | |
| { /* MPH_XAAUDIOENCODERCAPABILITIES */ NULL, NULL, NULL, NULL, NULL }, | |
| { /* MPH_XAAUDIOIODEVICECAPABILITIES */ NULL, NULL, NULL, NULL, NULL }, | |
| { /* MPH_XACAMERA */ NULL, NULL, NULL, NULL, NULL }, | |
| { /* MPH_XACAMERACAPABILITIES */ NULL, NULL, NULL, NULL, NULL }, | |
| { /* MPH_XACONFIGEXTENSION */ NULL, NULL, NULL, NULL, NULL }, | |
| { /* MPH_XADEVICEVOLUME */ NULL, NULL, NULL, NULL, NULL }, | |
| { /* MPH_XADYNAMICINTERFACEMANAGEMENT 59 */ NULL, NULL, NULL, NULL, NULL }, | |
| { /* MPH_XADYNAMICSOURCE */ NULL, NULL, NULL, NULL, NULL }, | |
| { /* MPH_XAENGINE */ IXAEngine_init, NULL, IXAEngine_deinit, NULL, NULL }, | |
| { /* MPH_XAEQUALIZER */ NULL, NULL, NULL, NULL, NULL }, | |
| { /* MPH_XAIMAGECONTROLS */ NULL, NULL, NULL, NULL, NULL }, | |
| { /* MPH_XAIMAGEDECODERCAPABILITIES */ NULL, NULL, NULL, NULL, NULL }, | |
| { /* MPH_XAIMAGEEFFECTS */ NULL, NULL, NULL, NULL, NULL }, | |
| { /* MPH_XAIMAGEENCODER */ NULL, NULL, NULL, NULL, NULL }, | |
| { /* MPH_XAIMAGEENCODERCAPABILITIES */ NULL, NULL, NULL, NULL, NULL }, | |
| { /* MPH_XALED */ NULL, NULL, NULL, NULL, NULL }, | |
| { /* MPH_XAMETADATAEXTRACTION */ NULL, NULL, NULL, NULL, NULL }, | |
| { /* MPH_XAMETADATAINSERTION */ NULL, NULL, NULL, NULL, NULL }, | |
| { /* MPH_XAMETADATATRAVERSAL */ NULL, NULL, NULL, NULL, NULL }, | |
| // { /* MPH_XANULL */ NULL, NULL, NULL, NULL, NULL }, | |
| { /* MPH_XAOBJECT */ IObject_init, NULL, IObject_deinit, NULL, NULL }, | |
| { /* MPH_XAOUTPUTMIX */ NULL, NULL, NULL, NULL, NULL }, | |
| { /* MPH_XAPLAY */ IPlay_init, NULL, NULL, NULL, NULL }, | |
| { /* MPH_XAPLAYBACKRATE */ NULL, NULL, NULL, NULL, NULL }, | |
| { /* MPH_XAPREFETCHSTATUS, */ IPrefetchStatus_init, NULL, NULL, NULL, NULL }, | |
| { /* MPH_XARADIO */ NULL, NULL, NULL, NULL, NULL }, | |
| { /* MPH_XARDS */ NULL, NULL, NULL, NULL, NULL }, | |
| { /* MPH_XARECORD */ NULL, NULL, NULL, NULL, NULL }, | |
| { /* MPH_XASEEK */ ISeek_init, NULL, NULL, NULL, NULL }, | |
| { /* MPH_XASNAPSHOT */ NULL, NULL, NULL, NULL, NULL }, | |
| { /* MPH_XASTREAMINFORMATION */ IStreamInformation_init, NULL, IStreamInformation_deinit, | |
| NULL, NULL }, | |
| { /* MPH_XATHREADSYNC */ NULL, NULL, NULL, NULL, NULL }, | |
| { /* MPH_XAVIBRA */ NULL, NULL, NULL, NULL, NULL }, | |
| { /* MPH_XAVIDEODECODERCAPABILITIES */ IVideoDecoderCapabilities_init, NULL, | |
| IVideoDecoderCapabilities_deinit, IVideoDecoderCapabilities_expose, NULL }, | |
| { /* MPH_XAVIDEOENCODER */ NULL, NULL, NULL, NULL, NULL }, | |
| { /* MPH_XAVIDEOENCODERCAPABILITIES */ NULL, NULL, NULL, NULL, NULL }, | |
| { /* MPH_XAVIDEOPOSTPROCESSING */ NULL, NULL, NULL, NULL, NULL }, | |
| { /* MPH_XAVOLUME, */ IVolume_init, NULL, NULL, NULL, NULL }, | |
| { /* MPH_ANDROIDACOUSTICECHOCANCELLATION, */ IAndroidAcousticEchoCancellation_init, NULL, | |
| IAndroidAcousticEchoCancellation_deinit, IAndroidAcousticEchoCancellation_Expose, | |
| NULL }, | |
| { /* MPH_ANDROIDAUTOMATICGAINCONTROL, */ IAndroidAutomaticGainControl_init, NULL, | |
| IAndroidAutomaticGainControl_deinit, IAndroidAutomaticGainControl_Expose, NULL }, | |
| { /* MPH_ANDROIDNOISESUPPRESSION, */ IAndroidNoiseSuppression_init, NULL, | |
| IAndroidNoiseSuppression_deinit, IAndroidNoiseSuppression_Expose, NULL }, | |
| }; | |
| /** \brief Construct a new instance of the specified class, exposing selected interfaces */ | |
| IObject *construct(const ClassTable *clazz, unsigned exposedMask, SLEngineItf engine) | |
| { | |
| IObject *thiz; | |
| // Do not change this to malloc; we depend on the object being memset to zero | |
| thiz = (IObject *) calloc(1, clazz->mSize); | |
| if (NULL != thiz) { | |
| SL_LOGV("construct %s at %p", clazz->mName, thiz); | |
| unsigned lossOfControlMask = 0; | |
| // a NULL engine means we are constructing the engine | |
| IEngine *thisEngine = (IEngine *) engine; | |
| if (NULL == thisEngine) { | |
| // thisEngine = &((CEngine *) thiz)->mEngine; | |
| thiz->mEngine = (CEngine *) thiz; | |
| } else { | |
| thiz->mEngine = (CEngine *) thisEngine->mThis; | |
| interface_lock_exclusive(thisEngine); | |
| if (MAX_INSTANCE <= thisEngine->mInstanceCount) { | |
| SL_LOGE("Too many objects"); | |
| interface_unlock_exclusive(thisEngine); | |
| free(thiz); | |
| return NULL; | |
| } | |
| // pre-allocate a pending slot, but don't assign bit from mInstanceMask yet | |
| ++thisEngine->mInstanceCount; | |
| assert(((unsigned) ~0) != thisEngine->mInstanceMask); | |
| interface_unlock_exclusive(thisEngine); | |
| // const, no lock needed | |
| if (thisEngine->mLossOfControlGlobal) { | |
| lossOfControlMask = ~0; | |
| } | |
| } | |
| thiz->mLossOfControlMask = lossOfControlMask; | |
| thiz->mClass = clazz; | |
| const struct iid_vtable *x = clazz->mInterfaces; | |
| SLuint8 *interfaceStateP = thiz->mInterfaceStates; | |
| SLuint32 index; | |
| for (index = 0; index < clazz->mInterfaceCount; ++index, ++x, exposedMask >>= 1) { | |
| SLuint8 state; | |
| // initialize all interfaces with init hooks, even if not exposed | |
| const struct MPH_init *mi = &MPH_init_table[x->mMPH]; | |
| VoidHook init = mi->mInit; | |
| if (NULL != init) { | |
| void *self = (char *) thiz + x->mOffset; | |
| // IObject does not have an mThis, so [1] is not always defined | |
| if (index) { | |
| ((IObject **) self)[1] = thiz; | |
| } | |
| // call the initialization hook | |
| (*init)(self); | |
| // IObject does not require a call to GetInterface | |
| if (index) { | |
| // This trickery invalidates the v-table until GetInterface | |
| ((size_t *) self)[0] ^= ~0; | |
| } | |
| // if interface is exposed, also call the optional expose hook | |
| BoolHook expose; | |
| state = (exposedMask & 1) && ((NULL == (expose = mi->mExpose)) || (*expose)(self)) ? | |
| INTERFACE_EXPOSED : INTERFACE_INITIALIZED; | |
| // FIXME log or report to application if an expose hook on a | |
| // required explicit interface fails at creation time | |
| } else { | |
| state = INTERFACE_UNINITIALIZED; | |
| } | |
| *interfaceStateP++ = state; | |
| } | |
| // note that the new object is not yet published; creator must call IObject_Publish | |
| } | |
| return thiz; | |
| } |