1773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi/*
2773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi * Copyright (C) 2010 The Android Open Source Project
3773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi *
4773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi * Licensed under the Apache License, Version 2.0 (the "License");
5773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi * you may not use this file except in compliance with the License.
6773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi * You may obtain a copy of the License at
7773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi *
8773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi *      http://www.apache.org/licenses/LICENSE-2.0
9773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi *
10773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi * Unless required by applicable law or agreed to in writing, software
11773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi * distributed under the License is distributed on an "AS IS" BASIS,
12773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi * See the License for the specific language governing permissions and
14773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi * limitations under the License.
15773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi */
16d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
17e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten/* OpenSL ES private and global functions not associated with an interface or class */
18d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
19773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi#include "sles_allinclusive.h"
20d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
21bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
22e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten/** \brief Return true if the specified interface exists and has been initialized for this object.
23e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten *  Returns false if the class does not support this kind of interface, or the class supports the
24e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten *  interface but this particular object has not had the interface exposed at object creation time
25e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten *  or by DynamicInterface::AddInterface. Note that the return value is not affected by whether
26e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten *  the application has requested access to the interface with Object::GetInterface. Assumes on
27e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten *  entry that the object is locked for either shared or exclusive access.
28e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten */
290b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
30bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kastenbool IsInterfaceInitialized(IObject *thiz, unsigned MPH)
31e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten{
32bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    assert(NULL != thiz);
33e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten    assert( /* (MPH_MIN <= MPH) && */ (MPH < (unsigned) MPH_MAX));
34bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    const ClassTable *clazz = thiz->mClass;
35bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    assert(NULL != clazz);
36e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten    int index;
37bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    if (0 > (index = clazz->mMPH_to_index[MPH])) {
38e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten        return false;
39928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    }
40bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    assert(MAX_INDEX >= clazz->mInterfaceCount);
41bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    assert(clazz->mInterfaceCount > (unsigned) index);
42bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    switch (thiz->mInterfaceStates[index]) {
43e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten    case INTERFACE_EXPOSED:
44e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten    case INTERFACE_ADDED:
45e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten        return true;
46e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten    default:
47e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten        return false;
48e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten    }
49e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten}
50e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten
51e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten
52e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten/** \brief Map an IObject to it's "object ID" (which is really a class ID) */
53b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten
54bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn KastenSLuint32 IObjectToObjectID(IObject *thiz)
55b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten{
56bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    assert(NULL != thiz);
579e0f457f2809f5f062ac052d4a304e8996b49a80Glenn Kasten    // Note this returns the OpenSL ES object ID in preference to the OpenMAX AL if both available
58bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    const ClassTable *clazz = thiz->mClass;
59bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    assert(NULL != clazz);
60bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    SLuint32 id = clazz->mSLObjectID;
61ab7724988c1ff39ad3fc95a7ae0e638357708f7cGlenn Kasten    if (!id) {
62bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        id = clazz->mXAObjectID;
63ab7724988c1ff39ad3fc95a7ae0e638357708f7cGlenn Kasten    }
6494a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten    return id;
65b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten}
66b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten
670b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
68928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten/** \brief Acquire a strong reference to an object.
69928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten *  Check that object has the specified "object ID" (which is really a class ID) and is in the
70928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten *  realized state.  If so, then acquire a strong reference to it and return true.
71928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten *  Otherwise return false.
72928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten */
73928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten
74928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn KastenSLresult AcquireStrongRef(IObject *object, SLuint32 expectedObjectID)
75928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten{
76928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    if (NULL == object) {
77928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
78928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    }
79928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    // NTH additional validity checks on address here
80928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    SLresult result;
81928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    object_lock_exclusive(object);
82928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    SLuint32 actualObjectID = IObjectToObjectID(object);
83928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    if (expectedObjectID != actualObjectID) {
84a8179ea15c4ff78db589d742b135649f0eda7ef2Glenn Kasten        SL_LOGE("object %p has object ID %u but expected %u", object, actualObjectID,
85928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten            expectedObjectID);
86928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
87928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    } else if (SL_OBJECT_STATE_REALIZED != object->mState) {
88a8179ea15c4ff78db589d742b135649f0eda7ef2Glenn Kasten        SL_LOGE("object %p with object ID %u is not realized", object, actualObjectID);
89928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten        result = SL_RESULT_PRECONDITIONS_VIOLATED;
90928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    } else {
91928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten        ++object->mStrongRefCount;
92928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten        result = SL_RESULT_SUCCESS;
93928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    }
94928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    object_unlock_exclusive(object);
95928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    return result;
96928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten}
97928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten
98928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten
99928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten/** \brief Release a strong reference to an object.
100928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten *  Entry condition: the object is locked.
101928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten *  Exit condition: the object is unlocked.
102928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten *  Finishes the destroy if needed.
103928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten */
104928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten
105928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kastenvoid ReleaseStrongRefAndUnlockExclusive(IObject *object)
106928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten{
107a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#ifdef USE_DEBUG
108928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    assert(pthread_equal(pthread_self(), object->mOwner));
109a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#endif
110928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    assert(0 < object->mStrongRefCount);
111928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    if ((0 == --object->mStrongRefCount) && (SL_OBJECT_STATE_DESTROYING == object->mState)) {
112928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten        // FIXME do the destroy here - merge with IDestroy
113928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten        // but can't do this until we move Destroy to the sync thread
114928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten        // as Destroy is now a blocking operation, and to avoid a race
115928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    } else {
116928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten        object_unlock_exclusive(object);
117928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    }
118928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten}
119928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten
120928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten
121928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten/** \brief Release a strong reference to an object.
122928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten *  Entry condition: the object is unlocked.
123928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten *  Exit condition: the object is unlocked.
124928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten *  Finishes the destroy if needed.
125928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten */
126928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten
127928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kastenvoid ReleaseStrongRef(IObject *object)
128928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten{
129928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    assert(NULL != object);
130928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    object_lock_exclusive(object);
131928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    ReleaseStrongRefAndUnlockExclusive(object);
132928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten}
133928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten
134928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten
135e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten/** \brief Convert POSIX pthread error code to OpenSL ES result code */
136d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten
137d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn KastenSLresult err_to_result(int err)
138d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten{
139f51dba65751107c930759938775b75531ec1f330Glenn Kasten    if (EAGAIN == err || ENOMEM == err) {
140d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten        return SL_RESULT_RESOURCE_ERROR;
141f51dba65751107c930759938775b75531ec1f330Glenn Kasten    }
142f51dba65751107c930759938775b75531ec1f330Glenn Kasten    if (0 != err) {
143d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten        return SL_RESULT_INTERNAL_ERROR;
144f51dba65751107c930759938775b75531ec1f330Glenn Kasten    }
145d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten    return SL_RESULT_SUCCESS;
146d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten}
147d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten
1480b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
149e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten/** \brief Check the interface IDs passed into a Create operation */
15029b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten
151bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn KastenSLresult checkInterfaces(const ClassTable *clazz, SLuint32 numInterfaces,
15205c7b2d09d54b9260ff7f3f5e491f38d0097c406Glenn Kasten    const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired,
15305c7b2d09d54b9260ff7f3f5e491f38d0097c406Glenn Kasten    unsigned *pExposedMask, unsigned *pRequiredMask)
154bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
155bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    assert(NULL != clazz && NULL != pExposedMask);
15601e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten    // Initially no interfaces are exposed
157bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    unsigned exposedMask = 0;
15805c7b2d09d54b9260ff7f3f5e491f38d0097c406Glenn Kasten    unsigned requiredMask = 0;
159bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    const struct iid_vtable *interfaces = clazz->mInterfaces;
160bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    SLuint32 interfaceCount = clazz->mInterfaceCount;
161bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLuint32 i;
16201e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten    // Expose all implicit interfaces
163bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    for (i = 0; i < interfaceCount; ++i) {
164bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        switch (interfaces[i].mInterface) {
165bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        case INTERFACE_IMPLICIT:
166104c000a6f36b871ca11e0394db1e5217f374cafGlenn Kasten        case INTERFACE_IMPLICIT_PREREALIZE:
167a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten            // there must be an initialization hook present
168a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten            if (NULL != MPH_init_table[interfaces[i].mMPH].mInit) {
169a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten                exposedMask |= 1 << i;
170a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten            }
171bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten            break;
1725e3b06982dbf1eae237cc74326e66d51d3cdd664Glenn Kasten        case INTERFACE_EXPLICIT:
1735e3b06982dbf1eae237cc74326e66d51d3cdd664Glenn Kasten        case INTERFACE_DYNAMIC:
1745e3b06982dbf1eae237cc74326e66d51d3cdd664Glenn Kasten        case INTERFACE_UNAVAILABLE:
1755e3b06982dbf1eae237cc74326e66d51d3cdd664Glenn Kasten        case INTERFACE_EXPLICIT_PREREALIZE:
1765e3b06982dbf1eae237cc74326e66d51d3cdd664Glenn Kasten            break;
177bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        default:
1785e3b06982dbf1eae237cc74326e66d51d3cdd664Glenn Kasten            assert(false);
179bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten            break;
180bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        }
181bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    }
182d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    if (0 < numInterfaces) {
183f51dba65751107c930759938775b75531ec1f330Glenn Kasten        if (NULL == pInterfaceIds || NULL == pInterfaceRequired) {
184d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten            return SL_RESULT_PARAMETER_INVALID;
185f51dba65751107c930759938775b75531ec1f330Glenn Kasten        }
186104c000a6f36b871ca11e0394db1e5217f374cafGlenn Kasten        bool anyRequiredButUnsupported = false;
18701e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten        // Loop for each requested interface
188d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten        for (i = 0; i < numInterfaces; ++i) {
189bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten            SLInterfaceID iid = pInterfaceIds[i];
190f51dba65751107c930759938775b75531ec1f330Glenn Kasten            if (NULL == iid) {
191bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten                return SL_RESULT_PARAMETER_INVALID;
192f51dba65751107c930759938775b75531ec1f330Glenn Kasten            }
19305c7b2d09d54b9260ff7f3f5e491f38d0097c406Glenn Kasten            SLboolean isRequired = pInterfaceRequired[i];
19429b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            int MPH, index;
19529b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            if ((0 > (MPH = IID_to_MPH(iid))) ||
196a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten                    // there must be an initialization hook present
197a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten                    (NULL == MPH_init_table[MPH].mInit) ||
198bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten                    (0 > (index = clazz->mMPH_to_index[MPH])) ||
199104c000a6f36b871ca11e0394db1e5217f374cafGlenn Kasten                    (INTERFACE_UNAVAILABLE == interfaces[index].mInterface)) {
20001e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten                // Here if interface was not found, or is not available for this object type
20105c7b2d09d54b9260ff7f3f5e491f38d0097c406Glenn Kasten                if (isRequired) {
20201e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten                    // Application said it required the interface, so give up
203a8179ea15c4ff78db589d742b135649f0eda7ef2Glenn Kasten                    SL_LOGE("class %s interface %u required but unavailable MPH=%d",
204bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten                            clazz->mName, i, MPH);
205104c000a6f36b871ca11e0394db1e5217f374cafGlenn Kasten                    anyRequiredButUnsupported = true;
206f51dba65751107c930759938775b75531ec1f330Glenn Kasten                }
207a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten                // Application said it didn't really need the interface, so ignore with warning
208a8179ea15c4ff78db589d742b135649f0eda7ef2Glenn Kasten                SL_LOGW("class %s interface %u requested but unavailable MPH=%d",
209bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten                        clazz->mName, i, MPH);
210bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten                continue;
211bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten            }
21205c7b2d09d54b9260ff7f3f5e491f38d0097c406Glenn Kasten            if (isRequired) {
21305c7b2d09d54b9260ff7f3f5e491f38d0097c406Glenn Kasten                requiredMask |= (1 << index);
21405c7b2d09d54b9260ff7f3f5e491f38d0097c406Glenn Kasten            }
21501e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten            // The requested interface was both found and available, so expose it
21629b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            exposedMask |= (1 << index);
21701e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten            // Note that we ignore duplicate requests, including equal and aliased IDs
218d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten        }
219104c000a6f36b871ca11e0394db1e5217f374cafGlenn Kasten        if (anyRequiredButUnsupported) {
220104c000a6f36b871ca11e0394db1e5217f374cafGlenn Kasten            return SL_RESULT_FEATURE_UNSUPPORTED;
221104c000a6f36b871ca11e0394db1e5217f374cafGlenn Kasten        }
222d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    }
223bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    *pExposedMask = exposedMask;
22405c7b2d09d54b9260ff7f3f5e491f38d0097c406Glenn Kasten    if (NULL != pRequiredMask) {
22505c7b2d09d54b9260ff7f3f5e491f38d0097c406Glenn Kasten        *pRequiredMask = requiredMask;
22605c7b2d09d54b9260ff7f3f5e491f38d0097c406Glenn Kasten    }
227d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    return SL_RESULT_SUCCESS;
228d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
229d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
2300b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
23161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten/* Interface initialization hooks */
2322045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
233a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kastenextern void
234a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    I3DCommit_init(void *),
235a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    I3DDoppler_init(void *),
236a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    I3DGrouping_init(void *),
237a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    I3DLocation_init(void *),
238a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    I3DMacroscopic_init(void *),
239a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    I3DSource_init(void *),
240f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean    IAndroidAcousticEchoCancellation_init(void *),
241f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean    IAndroidAutomaticGainControl_init(void *),
242a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten    IAndroidConfiguration_init(void *),
243a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IAndroidEffect_init(void *),
244a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten    IAndroidEffectCapabilities_init(void *),
245a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten    IAndroidEffectSend_init(void *),
246fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi    IAndroidBufferQueue_init(void *),
24761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IAudioDecoderCapabilities_init(void *),
24861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IAudioEncoder_init(void *),
249a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IAudioEncoderCapabilities_init(void *),
25061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IAudioIODeviceCapabilities_init(void *),
251a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IBassBoost_init(void *),
2520b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IBufferQueue_init(void *),
25361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IDeviceVolume_init(void *),
25461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IDynamicInterfaceManagement_init(void *),
25561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IDynamicSource_init(void *),
25661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IEffectSend_init(void *),
2570b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IEngine_init(void *),
258a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IEngineCapabilities_init(void *),
259a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IEnvironmentalReverb_init(void *),
260a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IEqualizer_init(void *),
26161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    ILEDArray_init(void *),
2620b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IMIDIMessage_init(void *),
2630b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IMIDIMuteSolo_init(void *),
2640b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IMIDITempo_init(void *),
2650b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IMIDITime_init(void *),
26661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IMetadataExtraction_init(void *),
26761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IMetadataTraversal_init(void *),
26861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IMuteSolo_init(void *),
269f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean    IAndroidNoiseSuppression_init(void *),
27061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IObject_init(void *),
2710b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IOutputMix_init(void *),
272a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IOutputMixExt_init(void *),
27361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IPitch_init(void *),
2740b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IPlay_init(void *),
27561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IPlaybackRate_init(void *),
27661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IPrefetchStatus_init(void *),
277a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IPresetReverb_init(void *),
27861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IRatePitch_init(void *),
27961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IRecord_init(void *),
2800b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    ISeek_init(void *),
28161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IThreadSync_init(void *),
28261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IVibra_init(void *),
283a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IVirtualizer_init(void *),
2840b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IVisualization_init(void *),
2856e7e174807fc639c49125ced8962aa369370fbf0Jean-Michel Trivi    IVolume_init(void *);
286a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten
2874597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kastenextern void
288a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    I3DGrouping_deinit(void *),
289f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean    IAndroidAcousticEchoCancellation_deinit(void *),
290f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean    IAndroidAutomaticGainControl_deinit(void *),
291a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IAndroidEffect_deinit(void *),
292a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IAndroidEffectCapabilities_deinit(void *),
293d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi    IAndroidBufferQueue_deinit(void *),
294f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean    IAndroidNoiseSuppression_deinit(void*),
295a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IBassBoost_deinit(void *),
296a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IBufferQueue_deinit(void *),
297a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IEngine_deinit(void *),
298a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IEnvironmentalReverb_deinit(void *),
299a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IEqualizer_deinit(void *),
300a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IObject_deinit(void *),
301a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IPresetReverb_deinit(void *),
302a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IThreadSync_deinit(void *),
3039f48e6a5f01aa87fab5c5cc867f8b078f96d1a45Paul McLean    IVirtualizer_deinit(void *),
3049f48e6a5f01aa87fab5c5cc867f8b078f96d1a45Paul McLean    IAndroidConfiguration_deinit(void *);
305a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten
306a9a70a4451545034c9263dd55b181f2912534c37Glenn Kastenextern bool
307f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean    IAndroidAcousticEchoCancellation_Expose(void *),
308f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean    IAndroidAutomaticGainControl_Expose(void *),
309a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IAndroidEffectCapabilities_Expose(void *),
310f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean    IAndroidNoiseSuppression_Expose(void *),
311a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IBassBoost_Expose(void *),
312a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IEnvironmentalReverb_Expose(void *),
313a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IEqualizer_Expose(void *),
314a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IPresetReverb_Expose(void *),
315a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IVirtualizer_Expose(void *);
316b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten
3178db0b106cdce5f5216b1535492de7930ad738aedGlenn Kastenextern void
3186e7e174807fc639c49125ced8962aa369370fbf0Jean-Michel Trivi    IXAEngine_init(void *),
3196e7e174807fc639c49125ced8962aa369370fbf0Jean-Michel Trivi    IStreamInformation_init(void*),
3206e7e174807fc639c49125ced8962aa369370fbf0Jean-Michel Trivi    IVideoDecoderCapabilities_init(void *);
3218db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
322faea005a67ba7e75faea571c521ad2e44fe3dc27Glenn Kastenextern void
3236e7e174807fc639c49125ced8962aa369370fbf0Jean-Michel Trivi    IXAEngine_deinit(void *),
3246e7e174807fc639c49125ced8962aa369370fbf0Jean-Michel Trivi    IStreamInformation_deinit(void *),
3256e7e174807fc639c49125ced8962aa369370fbf0Jean-Michel Trivi    IVideoDecoderCapabilities_deinit(void *);
3266e7e174807fc639c49125ced8962aa369370fbf0Jean-Michel Trivi
3276e7e174807fc639c49125ced8962aa369370fbf0Jean-Michel Triviextern bool
3286e7e174807fc639c49125ced8962aa369370fbf0Jean-Michel Trivi    IVideoDecoderCapabilities_expose(void *);
329faea005a67ba7e75faea571c521ad2e44fe3dc27Glenn Kasten
330a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#if !(USE_PROFILES & USE_PROFILES_MUSIC)
331a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IDynamicSource_init         NULL
332a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IMetadataTraversal_init     NULL
333a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IVisualization_init         NULL
334a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#endif
335a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten
336a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#if !(USE_PROFILES & USE_PROFILES_GAME)
337a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define I3DCommit_init      NULL
338a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define I3DDoppler_init     NULL
339a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define I3DGrouping_init    NULL
340a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define I3DLocation_init    NULL
341a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define I3DMacroscopic_init NULL
342a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define I3DSource_init      NULL
343a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IMIDIMessage_init   NULL
344a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IMIDIMuteSolo_init  NULL
345a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IMIDITempo_init     NULL
346a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IMIDITime_init      NULL
347a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IPitch_init         NULL
348a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IRatePitch_init     NULL
349a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define I3DGrouping_deinit  NULL
350a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#endif
351a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten
352a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#if !(USE_PROFILES & USE_PROFILES_BASE)
353a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IAudioDecoderCapabilities_init   NULL
354a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IAudioEncoderCapabilities_init   NULL
355a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IAudioEncoder_init               NULL
356a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IAudioIODeviceCapabilities_init  NULL
357a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IDeviceVolume_init               NULL
358a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IEngineCapabilities_init         NULL
359a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IThreadSync_init                 NULL
360a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten#define IThreadSync_deinit               NULL
361a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#endif
362a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten
363a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#if !(USE_PROFILES & USE_PROFILES_OPTIONAL)
364a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define ILEDArray_init  NULL
365a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IVibra_init     NULL
366a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#endif
367a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten
368a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#ifndef ANDROID
369a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten#define IAndroidConfiguration_init        NULL
3709f48e6a5f01aa87fab5c5cc867f8b078f96d1a45Paul McLean#define IAndroidConfiguration_deinit      NULL
371a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten#define IAndroidEffect_init               NULL
372a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten#define IAndroidEffectCapabilities_init   NULL
373a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten#define IAndroidEffectSend_init           NULL
374a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten#define IAndroidEffect_deinit             NULL
375a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten#define IAndroidEffectCapabilities_deinit NULL
376a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten#define IAndroidEffectCapabilities_Expose NULL
377fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi#define IAndroidBufferQueue_init          NULL
37837dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi#define IStreamInformation_init           NULL
379f6c0c2346b2ca1ac01c2d68a2cd2a7f1d9ff3427Glenn Kasten#define IAndroidBufferQueue_deinit        NULL
380f6c0c2346b2ca1ac01c2d68a2cd2a7f1d9ff3427Glenn Kasten#define IStreamInformation_deinit         NULL
381a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#endif
382a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten
383a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#ifndef USE_OUTPUTMIXEXT
384a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IOutputMixExt_init  NULL
385a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#endif
386a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten
387e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten
38861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten/*static*/ const struct MPH_init MPH_init_table[MPH_MAX] = {
389711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_3DCOMMIT, */ I3DCommit_init, NULL, NULL, NULL, NULL },
390711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_3DDOPPLER, */ I3DDoppler_init, NULL, NULL, NULL, NULL },
391711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_3DGROUPING, */ I3DGrouping_init, NULL, I3DGrouping_deinit, NULL, NULL },
392711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_3DLOCATION, */ I3DLocation_init, NULL, NULL, NULL, NULL },
393711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_3DMACROSCOPIC, */ I3DMacroscopic_init, NULL, NULL, NULL, NULL },
394711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_3DSOURCE, */ I3DSource_init, NULL, NULL, NULL, NULL },
395711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_AUDIODECODERCAPABILITIES, */ IAudioDecoderCapabilities_init, NULL, NULL, NULL, NULL },
396711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_AUDIOENCODER, */ IAudioEncoder_init, NULL, NULL, NULL, NULL },
397711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_AUDIOENCODERCAPABILITIES, */ IAudioEncoderCapabilities_init, NULL, NULL, NULL, NULL },
398711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_AUDIOIODEVICECAPABILITIES, */ IAudioIODeviceCapabilities_init, NULL, NULL, NULL,
399711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten        NULL },
400711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_BASSBOOST, */ IBassBoost_init, NULL, IBassBoost_deinit, IBassBoost_Expose, NULL },
401711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_BUFFERQUEUE, */ IBufferQueue_init, NULL, IBufferQueue_deinit, NULL, NULL },
402711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_DEVICEVOLUME, */ IDeviceVolume_init, NULL, NULL, NULL, NULL },
403711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_DYNAMICINTERFACEMANAGEMENT, */ IDynamicInterfaceManagement_init, NULL, NULL, NULL,
404711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten        NULL },
405711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_DYNAMICSOURCE, */ IDynamicSource_init, NULL, NULL, NULL, NULL },
406711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_EFFECTSEND, */ IEffectSend_init, NULL, NULL, NULL, NULL },
407711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_ENGINE, */ IEngine_init, NULL, IEngine_deinit, NULL, NULL },
408711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_ENGINECAPABILITIES, */ IEngineCapabilities_init, NULL, NULL, NULL, NULL },
409a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    { /* MPH_ENVIRONMENTALREVERB, */ IEnvironmentalReverb_init, NULL, IEnvironmentalReverb_deinit,
410711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten        IEnvironmentalReverb_Expose, NULL },
411711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_EQUALIZER, */ IEqualizer_init, NULL, IEqualizer_deinit, IEqualizer_Expose, NULL },
412711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_LED, */ ILEDArray_init, NULL, NULL, NULL, NULL },
413711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_METADATAEXTRACTION, */ IMetadataExtraction_init, NULL, NULL, NULL, NULL },
414711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_METADATATRAVERSAL, */ IMetadataTraversal_init, NULL, NULL, NULL, NULL },
415711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_MIDIMESSAGE, */ IMIDIMessage_init, NULL, NULL, NULL, NULL },
416711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_MIDITIME, */ IMIDITime_init, NULL, NULL, NULL, NULL },
417711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_MIDITEMPO, */ IMIDITempo_init, NULL, NULL, NULL, NULL },
418711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_MIDIMUTESOLO, */ IMIDIMuteSolo_init, NULL, NULL, NULL, NULL },
419711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_MUTESOLO, */ IMuteSolo_init, NULL, NULL, NULL, NULL },
420711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_NULL, */ NULL, NULL, NULL, NULL, NULL },
421711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_OBJECT, */ IObject_init, NULL, IObject_deinit, NULL, NULL },
422711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_OUTPUTMIX, */ IOutputMix_init, NULL, NULL, NULL, NULL },
423711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_PITCH, */ IPitch_init, NULL, NULL, NULL, NULL },
424711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_PLAY, */ IPlay_init, NULL, NULL, NULL, NULL },
425711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_PLAYBACKRATE, */ IPlaybackRate_init, NULL, NULL, NULL, NULL },
426711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_PREFETCHSTATUS, */ IPrefetchStatus_init, NULL, NULL, NULL, NULL },
427a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    { /* MPH_PRESETREVERB, */ IPresetReverb_init, NULL, IPresetReverb_deinit,
428711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten        IPresetReverb_Expose, NULL },
429711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_RATEPITCH, */ IRatePitch_init, NULL, NULL, NULL, NULL },
430711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_RECORD, */ IRecord_init, NULL, NULL, NULL, NULL },
431711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_SEEK, */ ISeek_init, NULL, NULL, NULL, NULL },
432711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_THREADSYNC, */ IThreadSync_init, NULL, IThreadSync_deinit, NULL, NULL },
433711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_VIBRA, */ IVibra_init, NULL, NULL, NULL, NULL },
434711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_VIRTUALIZER, */ IVirtualizer_init, NULL, IVirtualizer_deinit, IVirtualizer_Expose,
435711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten        NULL },
436711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_VISUALIZATION, */ IVisualization_init, NULL, NULL, NULL, NULL },
437711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_VOLUME, */ IVolume_init, NULL, NULL, NULL, NULL },
438b0ab2dee391dd2cb257faeaba252ee6ecccc5f03Glenn Kasten// Wilhelm desktop extended interfaces
439711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_OUTPUTMIXEXT, */ IOutputMixExt_init, NULL, NULL, NULL, NULL },
440b0ab2dee391dd2cb257faeaba252ee6ecccc5f03Glenn Kasten// Android API level 9 extended interfaces
441711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_ANDROIDEFFECT */ IAndroidEffect_init, NULL, IAndroidEffect_deinit, NULL, NULL },
442a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    { /* MPH_ANDROIDEFFECTCAPABILITIES */ IAndroidEffectCapabilities_init, NULL,
443711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten        IAndroidEffectCapabilities_deinit, IAndroidEffectCapabilities_Expose, NULL },
444711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_ANDROIDEFFECTSEND */ IAndroidEffectSend_init, NULL, NULL, NULL, NULL },
4459f48e6a5f01aa87fab5c5cc867f8b078f96d1a45Paul McLean    { /* MPH_ANDROIDCONFIGURATION */ IAndroidConfiguration_init, NULL, IAndroidConfiguration_deinit,
4469f48e6a5f01aa87fab5c5cc867f8b078f96d1a45Paul McLean            NULL, NULL },
44728bc6b725c207fb8fbd618caea4aa127f35ce1e1Jean-Michel Trivi    { /* MPH_ANDROIDSIMPLEBUFFERQUEUE */ IBufferQueue_init /* alias */, NULL, NULL, NULL, NULL },
448b0ab2dee391dd2cb257faeaba252ee6ecccc5f03Glenn Kasten// Android API level 10 extended interfaces
44960ca9f9ef02f6e486c3338cb811f603dd7825c05Glenn Kasten    { /* MPH_ANDROIDBUFFERQUEUESOURCE */ IAndroidBufferQueue_init, NULL, IAndroidBufferQueue_deinit,
45060ca9f9ef02f6e486c3338cb811f603dd7825c05Glenn Kasten        NULL, NULL },
4518db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten// OpenMAX AL 1.0.1 interfaces
452faea005a67ba7e75faea571c521ad2e44fe3dc27Glenn Kasten    { /* MPH_XAAUDIODECODERCAPABILITIES */ NULL, NULL, NULL, NULL, NULL },
453faea005a67ba7e75faea571c521ad2e44fe3dc27Glenn Kasten    { /* MPH_XAAUDIOENCODER */ NULL, NULL, NULL, NULL, NULL },
454faea005a67ba7e75faea571c521ad2e44fe3dc27Glenn Kasten    { /* MPH_XAAUDIOENCODERCAPABILITIES */ NULL, NULL, NULL, NULL, NULL },
455faea005a67ba7e75faea571c521ad2e44fe3dc27Glenn Kasten    { /* MPH_XAAUDIOIODEVICECAPABILITIES */ NULL, NULL, NULL, NULL, NULL },
456faea005a67ba7e75faea571c521ad2e44fe3dc27Glenn Kasten    { /* MPH_XACAMERA */ NULL, NULL, NULL, NULL, NULL },
457faea005a67ba7e75faea571c521ad2e44fe3dc27Glenn Kasten    { /* MPH_XACAMERACAPABILITIES */ NULL, NULL, NULL, NULL, NULL },
458faea005a67ba7e75faea571c521ad2e44fe3dc27Glenn Kasten    { /* MPH_XACONFIGEXTENSION */ NULL, NULL, NULL, NULL, NULL },
459faea005a67ba7e75faea571c521ad2e44fe3dc27Glenn Kasten    { /* MPH_XADEVICEVOLUME */ NULL, NULL, NULL, NULL, NULL },
460faea005a67ba7e75faea571c521ad2e44fe3dc27Glenn Kasten    { /* MPH_XADYNAMICINTERFACEMANAGEMENT 59 */ NULL, NULL, NULL, NULL, NULL },
461faea005a67ba7e75faea571c521ad2e44fe3dc27Glenn Kasten    { /* MPH_XADYNAMICSOURCE */ NULL, NULL, NULL, NULL, NULL },
462faea005a67ba7e75faea571c521ad2e44fe3dc27Glenn Kasten    { /* MPH_XAENGINE */ IXAEngine_init, NULL, IXAEngine_deinit, NULL, NULL },
463faea005a67ba7e75faea571c521ad2e44fe3dc27Glenn Kasten    { /* MPH_XAEQUALIZER */ NULL, NULL, NULL, NULL, NULL },
464faea005a67ba7e75faea571c521ad2e44fe3dc27Glenn Kasten    { /* MPH_XAIMAGECONTROLS */ NULL, NULL, NULL, NULL, NULL },
465faea005a67ba7e75faea571c521ad2e44fe3dc27Glenn Kasten    { /* MPH_XAIMAGEDECODERCAPABILITIES */ NULL, NULL, NULL, NULL, NULL },
466faea005a67ba7e75faea571c521ad2e44fe3dc27Glenn Kasten    { /* MPH_XAIMAGEEFFECTS */ NULL, NULL, NULL, NULL, NULL },
467faea005a67ba7e75faea571c521ad2e44fe3dc27Glenn Kasten    { /* MPH_XAIMAGEENCODER */ NULL, NULL, NULL, NULL, NULL },
468faea005a67ba7e75faea571c521ad2e44fe3dc27Glenn Kasten    { /* MPH_XAIMAGEENCODERCAPABILITIES */ NULL, NULL, NULL, NULL, NULL },
469faea005a67ba7e75faea571c521ad2e44fe3dc27Glenn Kasten    { /* MPH_XALED */ NULL, NULL, NULL, NULL, NULL },
470faea005a67ba7e75faea571c521ad2e44fe3dc27Glenn Kasten    { /* MPH_XAMETADATAEXTRACTION */ NULL, NULL, NULL, NULL, NULL },
471faea005a67ba7e75faea571c521ad2e44fe3dc27Glenn Kasten    { /* MPH_XAMETADATAINSERTION */ NULL, NULL, NULL, NULL, NULL },
472faea005a67ba7e75faea571c521ad2e44fe3dc27Glenn Kasten    { /* MPH_XAMETADATATRAVERSAL */ NULL, NULL, NULL, NULL, NULL },
473faea005a67ba7e75faea571c521ad2e44fe3dc27Glenn Kasten//  { /* MPH_XANULL */ NULL, NULL, NULL, NULL, NULL },
474faea005a67ba7e75faea571c521ad2e44fe3dc27Glenn Kasten    { /* MPH_XAOBJECT */ IObject_init, NULL, IObject_deinit, NULL, NULL },
475faea005a67ba7e75faea571c521ad2e44fe3dc27Glenn Kasten    { /* MPH_XAOUTPUTMIX */ NULL, NULL, NULL, NULL, NULL },
47694a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten    { /* MPH_XAPLAY */ IPlay_init, NULL, NULL, NULL, NULL },
477faea005a67ba7e75faea571c521ad2e44fe3dc27Glenn Kasten    { /* MPH_XAPLAYBACKRATE */ NULL, NULL, NULL, NULL, NULL },
478c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten    { /* MPH_XAPREFETCHSTATUS, */ IPrefetchStatus_init, NULL, NULL, NULL, NULL },
479faea005a67ba7e75faea571c521ad2e44fe3dc27Glenn Kasten    { /* MPH_XARADIO */ NULL, NULL, NULL, NULL, NULL },
480faea005a67ba7e75faea571c521ad2e44fe3dc27Glenn Kasten    { /* MPH_XARDS */ NULL, NULL, NULL, NULL, NULL },
481faea005a67ba7e75faea571c521ad2e44fe3dc27Glenn Kasten    { /* MPH_XARECORD */ NULL, NULL, NULL, NULL, NULL },
48292b245bf8828db9e469febebbe8774c00570b5b9Jean-Michel Trivi    { /* MPH_XASEEK */ ISeek_init, NULL, NULL, NULL, NULL },
483faea005a67ba7e75faea571c521ad2e44fe3dc27Glenn Kasten    { /* MPH_XASNAPSHOT */ NULL, NULL, NULL, NULL, NULL },
48437dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi    { /* MPH_XASTREAMINFORMATION */ IStreamInformation_init, NULL, IStreamInformation_deinit,
48537dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi        NULL, NULL },
486faea005a67ba7e75faea571c521ad2e44fe3dc27Glenn Kasten    { /* MPH_XATHREADSYNC */ NULL, NULL, NULL, NULL, NULL },
487faea005a67ba7e75faea571c521ad2e44fe3dc27Glenn Kasten    { /* MPH_XAVIBRA */ NULL, NULL, NULL, NULL, NULL },
4886e7e174807fc639c49125ced8962aa369370fbf0Jean-Michel Trivi    { /* MPH_XAVIDEODECODERCAPABILITIES */ IVideoDecoderCapabilities_init, NULL,
4896e7e174807fc639c49125ced8962aa369370fbf0Jean-Michel Trivi            IVideoDecoderCapabilities_deinit, IVideoDecoderCapabilities_expose, NULL },
490faea005a67ba7e75faea571c521ad2e44fe3dc27Glenn Kasten    { /* MPH_XAVIDEOENCODER */ NULL, NULL, NULL, NULL, NULL },
491faea005a67ba7e75faea571c521ad2e44fe3dc27Glenn Kasten    { /* MPH_XAVIDEOENCODERCAPABILITIES */ NULL, NULL, NULL, NULL, NULL },
492faea005a67ba7e75faea571c521ad2e44fe3dc27Glenn Kasten    { /* MPH_XAVIDEOPOSTPROCESSING */ NULL, NULL, NULL, NULL, NULL },
49337dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi    { /* MPH_XAVOLUME, */ IVolume_init, NULL, NULL, NULL, NULL },
494f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean    { /* MPH_ANDROIDACOUSTICECHOCANCELLATION, */ IAndroidAcousticEchoCancellation_init, NULL,
495f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean            IAndroidAcousticEchoCancellation_deinit, IAndroidAcousticEchoCancellation_Expose,
496f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean            NULL },
497f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean    { /* MPH_ANDROIDAUTOMATICGAINCONTROL, */ IAndroidAutomaticGainControl_init, NULL,
498f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean            IAndroidAutomaticGainControl_deinit, IAndroidAutomaticGainControl_Expose, NULL },
499f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean    { /* MPH_ANDROIDNOISESUPPRESSION, */ IAndroidNoiseSuppression_init, NULL,
500f8b3141926967ba37d315cc8d3956d7214958e6bPaul McLean            IAndroidNoiseSuppression_deinit, IAndroidNoiseSuppression_Expose, NULL },
501bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten};
502bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
5030b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
504e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten/** \brief Construct a new instance of the specified class, exposing selected interfaces */
505bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
506bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn KastenIObject *construct(const ClassTable *clazz, unsigned exposedMask, SLEngineItf engine)
507bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
508bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    IObject *thiz;
509f6f5ceb363286d5ebef2c2e70c8a5aa135d5d1eeGlenn Kasten    // Do not change this to malloc; we depend on the object being memset to zero
510bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    thiz = (IObject *) calloc(1, clazz->mSize);
511bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    if (NULL != thiz) {
512bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        SL_LOGV("construct %s at %p", clazz->mName, thiz);
51372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        unsigned lossOfControlMask = 0;
514ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten        // a NULL engine means we are constructing the engine
51572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        IEngine *thisEngine = (IEngine *) engine;
516d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten        if (NULL == thisEngine) {
517bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten            // thisEngine = &((CEngine *) thiz)->mEngine;
518bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten            thiz->mEngine = (CEngine *) thiz;
519d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten        } else {
520bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten            thiz->mEngine = (CEngine *) thisEngine->mThis;
521ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten            interface_lock_exclusive(thisEngine);
522d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten            if (MAX_INSTANCE <= thisEngine->mInstanceCount) {
523f51dba65751107c930759938775b75531ec1f330Glenn Kasten                SL_LOGE("Too many objects");
524ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten                interface_unlock_exclusive(thisEngine);
525bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten                free(thiz);
526ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten                return NULL;
527ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten            }
528d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten            // pre-allocate a pending slot, but don't assign bit from mInstanceMask yet
529ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten            ++thisEngine->mInstanceCount;
530d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten            assert(((unsigned) ~0) != thisEngine->mInstanceMask);
531ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten            interface_unlock_exclusive(thisEngine);
532ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten            // const, no lock needed
533f51dba65751107c930759938775b75531ec1f330Glenn Kasten            if (thisEngine->mLossOfControlGlobal) {
534ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten                lossOfControlMask = ~0;
535f51dba65751107c930759938775b75531ec1f330Glenn Kasten            }
536ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten        }
537bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        thiz->mLossOfControlMask = lossOfControlMask;
538bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        thiz->mClass = clazz;
539bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        const struct iid_vtable *x = clazz->mInterfaces;
540bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        SLuint8 *interfaceStateP = thiz->mInterfaceStates;
541510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        SLuint32 index;
542bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        for (index = 0; index < clazz->mInterfaceCount; ++index, ++x, exposedMask >>= 1) {
543276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten            SLuint8 state;
544a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten            // initialize all interfaces with init hooks, even if not exposed
545a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten            const struct MPH_init *mi = &MPH_init_table[x->mMPH];
546a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten            VoidHook init = mi->mInit;
547a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten            if (NULL != init) {
548bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten                void *self = (char *) thiz + x->mOffset;
549d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten                // IObject does not have an mThis, so [1] is not always defined
550f51dba65751107c930759938775b75531ec1f330Glenn Kasten                if (index) {
551bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten                    ((IObject **) self)[1] = thiz;
552f51dba65751107c930759938775b75531ec1f330Glenn Kasten                }
553a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten                // call the initialization hook
554a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten                (*init)(self);
555e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten                // IObject does not require a call to GetInterface
556f51dba65751107c930759938775b75531ec1f330Glenn Kasten                if (index) {
557711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten                    // This trickery invalidates the v-table until GetInterface
558e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten                    ((size_t *) self)[0] ^= ~0;
559f51dba65751107c930759938775b75531ec1f330Glenn Kasten                }
560a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten                // if interface is exposed, also call the optional expose hook
561a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten                BoolHook expose;
562a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten                state = (exposedMask & 1) && ((NULL == (expose = mi->mExpose)) || (*expose)(self)) ?
563a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten                        INTERFACE_EXPOSED : INTERFACE_INITIALIZED;
564a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten                // FIXME log or report to application if an expose hook on a
565a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten                // required explicit interface fails at creation time
566f51dba65751107c930759938775b75531ec1f330Glenn Kasten            } else {
567510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten                state = INTERFACE_UNINITIALIZED;
568f51dba65751107c930759938775b75531ec1f330Glenn Kasten            }
569510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            *interfaceStateP++ = state;
570bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        }
571f51dba65751107c930759938775b75531ec1f330Glenn Kasten        // note that the new object is not yet published; creator must call IObject_Publish
572bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    }
573bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    return thiz;
574bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
575