sles.cpp revision 94a37e8117fb72790882dfb815f99e2365754c74
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
30e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kastenbool IsInterfaceInitialized(IObject *this, unsigned MPH)
31e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten{
32e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten    assert(NULL != this);
33e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten    assert( /* (MPH_MIN <= MPH) && */ (MPH < (unsigned) MPH_MAX));
34e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten    const ClassTable *class__ = this->mClass;
35e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten    assert(NULL != class__);
36e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten    int index;
37928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    if (0 > (index = class__->mMPH_to_index[MPH])) {
38e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten        return false;
39928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    }
40e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten    assert(MAX_INDEX >= class__->mInterfaceCount);
41e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten    assert(class__->mInterfaceCount > (unsigned) index);
42e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten    switch (this->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
54b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn KastenSLuint32 IObjectToObjectID(IObject *this)
55b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten{
56b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    assert(NULL != this);
5794a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten    // FIXME Note this returns the SLES object ID in preference to the OMX AL if both available
5894a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten    const ClassTable *class__ = this->mClass;
5994a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten    assert(NULL != class__);
6094a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten    SLuint32 id = class__->mSLObjectID;
6194a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten    if (!id)
6294a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        id = class__->mXAObjectID;
6394a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten    return id;
64b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten}
65b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten
660b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
67928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten/** \brief Acquire a strong reference to an object.
68928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten *  Check that object has the specified "object ID" (which is really a class ID) and is in the
69928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten *  realized state.  If so, then acquire a strong reference to it and return true.
70928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten *  Otherwise return false.
71928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten */
72928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten
73928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn KastenSLresult AcquireStrongRef(IObject *object, SLuint32 expectedObjectID)
74928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten{
75928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    if (NULL == object) {
76928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
77928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    }
78928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    // NTH additional validity checks on address here
79928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    SLresult result;
80928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    object_lock_exclusive(object);
81928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    SLuint32 actualObjectID = IObjectToObjectID(object);
82928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    if (expectedObjectID != actualObjectID) {
83928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten        SL_LOGE("object %p has object ID %lu but expected %lu", object, actualObjectID,
84928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten            expectedObjectID);
85928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
86928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    } else if (SL_OBJECT_STATE_REALIZED != object->mState) {
87928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten        SL_LOGE("object %p with object ID %lu is not realized", object, actualObjectID);
88928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten        result = SL_RESULT_PRECONDITIONS_VIOLATED;
89928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    } else {
90928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten        ++object->mStrongRefCount;
91928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten        result = SL_RESULT_SUCCESS;
92928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    }
93928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    object_unlock_exclusive(object);
94928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    return result;
95928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten}
96928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten
97928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten
98928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten/** \brief Release a strong reference to an object.
99928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten *  Entry condition: the object is locked.
100928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten *  Exit condition: the object is unlocked.
101928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten *  Finishes the destroy if needed.
102928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten */
103928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten
104928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kastenvoid ReleaseStrongRefAndUnlockExclusive(IObject *object)
105928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten{
106a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#ifdef USE_DEBUG
107928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    assert(pthread_equal(pthread_self(), object->mOwner));
108a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#endif
109928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    assert(0 < object->mStrongRefCount);
110928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    if ((0 == --object->mStrongRefCount) && (SL_OBJECT_STATE_DESTROYING == object->mState)) {
111928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten        // FIXME do the destroy here - merge with IDestroy
112928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten        // but can't do this until we move Destroy to the sync thread
113928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten        // as Destroy is now a blocking operation, and to avoid a race
114928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    } else {
115928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten        object_unlock_exclusive(object);
116928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    }
117928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten}
118928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten
119928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten
120928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten/** \brief Release a strong reference to an object.
121928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten *  Entry condition: the object is unlocked.
122928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten *  Exit condition: the object is unlocked.
123928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten *  Finishes the destroy if needed.
124928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten */
125928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten
126928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kastenvoid ReleaseStrongRef(IObject *object)
127928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten{
128928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    assert(NULL != object);
129928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    object_lock_exclusive(object);
130928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    ReleaseStrongRefAndUnlockExclusive(object);
131928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten}
132928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten
133928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten
134e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten/** \brief Convert POSIX pthread error code to OpenSL ES result code */
135d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten
136d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn KastenSLresult err_to_result(int err)
137d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten{
138f51dba65751107c930759938775b75531ec1f330Glenn Kasten    if (EAGAIN == err || ENOMEM == err) {
139d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten        return SL_RESULT_RESOURCE_ERROR;
140f51dba65751107c930759938775b75531ec1f330Glenn Kasten    }
141f51dba65751107c930759938775b75531ec1f330Glenn Kasten    if (0 != err) {
142d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten        return SL_RESULT_INTERNAL_ERROR;
143f51dba65751107c930759938775b75531ec1f330Glenn Kasten    }
144d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten    return SL_RESULT_SUCCESS;
145d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten}
146d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten
1470b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
148e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten/** \brief Check the interface IDs passed into a Create operation */
14929b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten
150ed46c29d6a09112dbbf584c82953f63289596fd6Glenn KastenSLresult checkInterfaces(const ClassTable *class__, SLuint32 numInterfaces,
151ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired, unsigned *pExposedMask)
152bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
153bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    assert(NULL != class__ && NULL != pExposedMask);
15401e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten    // Initially no interfaces are exposed
155bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    unsigned exposedMask = 0;
156bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    const struct iid_vtable *interfaces = class__->mInterfaces;
157bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLuint32 interfaceCount = class__->mInterfaceCount;
158bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLuint32 i;
15901e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten    // Expose all implicit interfaces
160bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    for (i = 0; i < interfaceCount; ++i) {
161bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        switch (interfaces[i].mInterface) {
162bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        case INTERFACE_IMPLICIT:
163104c000a6f36b871ca11e0394db1e5217f374cafGlenn Kasten        case INTERFACE_IMPLICIT_PREREALIZE:
164a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten            // there must be an initialization hook present
165a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten            if (NULL != MPH_init_table[interfaces[i].mMPH].mInit) {
166a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten                exposedMask |= 1 << i;
167a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten            }
168bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten            break;
1695e3b06982dbf1eae237cc74326e66d51d3cdd664Glenn Kasten        case INTERFACE_EXPLICIT:
1705e3b06982dbf1eae237cc74326e66d51d3cdd664Glenn Kasten        case INTERFACE_DYNAMIC:
1715e3b06982dbf1eae237cc74326e66d51d3cdd664Glenn Kasten        case INTERFACE_UNAVAILABLE:
1725e3b06982dbf1eae237cc74326e66d51d3cdd664Glenn Kasten        case INTERFACE_EXPLICIT_PREREALIZE:
1735e3b06982dbf1eae237cc74326e66d51d3cdd664Glenn Kasten            break;
174bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        default:
1755e3b06982dbf1eae237cc74326e66d51d3cdd664Glenn Kasten            assert(false);
176bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten            break;
177bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        }
178bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    }
179d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    if (0 < numInterfaces) {
180f51dba65751107c930759938775b75531ec1f330Glenn Kasten        if (NULL == pInterfaceIds || NULL == pInterfaceRequired) {
181d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten            return SL_RESULT_PARAMETER_INVALID;
182f51dba65751107c930759938775b75531ec1f330Glenn Kasten        }
183104c000a6f36b871ca11e0394db1e5217f374cafGlenn Kasten        bool anyRequiredButUnsupported = false;
18401e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten        // Loop for each requested interface
185d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten        for (i = 0; i < numInterfaces; ++i) {
186bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten            SLInterfaceID iid = pInterfaceIds[i];
187f51dba65751107c930759938775b75531ec1f330Glenn Kasten            if (NULL == iid) {
188bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten                return SL_RESULT_PARAMETER_INVALID;
189f51dba65751107c930759938775b75531ec1f330Glenn Kasten            }
19029b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            int MPH, index;
19129b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            if ((0 > (MPH = IID_to_MPH(iid))) ||
192a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten                    // there must be an initialization hook present
193a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten                    (NULL == MPH_init_table[MPH].mInit) ||
194104c000a6f36b871ca11e0394db1e5217f374cafGlenn Kasten                    (0 > (index = class__->mMPH_to_index[MPH])) ||
195104c000a6f36b871ca11e0394db1e5217f374cafGlenn Kasten                    (INTERFACE_UNAVAILABLE == interfaces[index].mInterface)) {
19601e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten                // Here if interface was not found, or is not available for this object type
197f51dba65751107c930759938775b75531ec1f330Glenn Kasten                if (pInterfaceRequired[i]) {
19801e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten                    // Application said it required the interface, so give up
19901e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten                    SL_LOGE("class %s interface %lu required but unavailable MPH=%d",
20001e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten                            class__->mName, i, MPH);
201104c000a6f36b871ca11e0394db1e5217f374cafGlenn Kasten                    anyRequiredButUnsupported = true;
202f51dba65751107c930759938775b75531ec1f330Glenn Kasten                }
203a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten                // Application said it didn't really need the interface, so ignore with warning
204a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten                SL_LOGW("class %s interface %lu requested but unavailable MPH=%d",
205a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten                        class__->mName, i, MPH);
206bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten                continue;
207bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten            }
20801e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten            // The requested interface was both found and available, so expose it
20929b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            exposedMask |= (1 << index);
21001e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten            // Note that we ignore duplicate requests, including equal and aliased IDs
211d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten        }
212104c000a6f36b871ca11e0394db1e5217f374cafGlenn Kasten        if (anyRequiredButUnsupported) {
213104c000a6f36b871ca11e0394db1e5217f374cafGlenn Kasten            return SL_RESULT_FEATURE_UNSUPPORTED;
214104c000a6f36b871ca11e0394db1e5217f374cafGlenn Kasten        }
215d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    }
216bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    *pExposedMask = exposedMask;
217d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    return SL_RESULT_SUCCESS;
218d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
219d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
2200b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
22161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten/* Interface initialization hooks */
2222045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
223a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kastenextern void
224a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    I3DCommit_init(void *),
225a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    I3DDoppler_init(void *),
226a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    I3DGrouping_init(void *),
227a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    I3DLocation_init(void *),
228a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    I3DMacroscopic_init(void *),
229a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    I3DSource_init(void *),
230a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten    IAndroidConfiguration_init(void *),
231a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IAndroidEffect_init(void *),
232a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten    IAndroidEffectCapabilities_init(void *),
233a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten    IAndroidEffectSend_init(void *),
234fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi    IAndroidBufferQueue_init(void *),
23561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IAudioDecoderCapabilities_init(void *),
23661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IAudioEncoder_init(void *),
237a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IAudioEncoderCapabilities_init(void *),
23861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IAudioIODeviceCapabilities_init(void *),
239a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IBassBoost_init(void *),
2400b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IBufferQueue_init(void *),
24161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IDeviceVolume_init(void *),
24261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IDynamicInterfaceManagement_init(void *),
24361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IDynamicSource_init(void *),
24461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IEffectSend_init(void *),
2450b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IEngine_init(void *),
246a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IEngineCapabilities_init(void *),
247a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IEnvironmentalReverb_init(void *),
248a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IEqualizer_init(void *),
24961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    ILEDArray_init(void *),
2500b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IMIDIMessage_init(void *),
2510b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IMIDIMuteSolo_init(void *),
2520b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IMIDITempo_init(void *),
2530b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IMIDITime_init(void *),
25461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IMetadataExtraction_init(void *),
25561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IMetadataTraversal_init(void *),
25661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IMuteSolo_init(void *),
25761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IObject_init(void *),
2580b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IOutputMix_init(void *),
259a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IOutputMixExt_init(void *),
26061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IPitch_init(void *),
2610b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IPlay_init(void *),
26261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IPlaybackRate_init(void *),
26361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IPrefetchStatus_init(void *),
264a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IPresetReverb_init(void *),
26561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IRatePitch_init(void *),
26661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IRecord_init(void *),
2670b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    ISeek_init(void *),
26861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IThreadSync_init(void *),
26961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IVibra_init(void *),
270a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IVirtualizer_init(void *),
2710b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IVisualization_init(void *),
2720b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IVolume_init(void *);
273a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten
2744597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kastenextern void
275a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    I3DGrouping_deinit(void *),
276a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IAndroidEffect_deinit(void *),
277a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IAndroidEffectCapabilities_deinit(void *),
278a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IBassBoost_deinit(void *),
279a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IBufferQueue_deinit(void *),
280a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IEngine_deinit(void *),
281a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IEnvironmentalReverb_deinit(void *),
282a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IEqualizer_deinit(void *),
283a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IObject_deinit(void *),
284a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IPresetReverb_deinit(void *),
285a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IThreadSync_deinit(void *),
286a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IVirtualizer_deinit(void *);
287a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten
288a9a70a4451545034c9263dd55b181f2912534c37Glenn Kastenextern bool
289a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IAndroidEffectCapabilities_Expose(void *),
290a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IBassBoost_Expose(void *),
291a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IEnvironmentalReverb_Expose(void *),
292a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IEqualizer_Expose(void *),
293a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IPresetReverb_Expose(void *),
294a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IVirtualizer_Expose(void *);
295b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten
2968db0b106cdce5f5216b1535492de7930ad738aedGlenn Kastenextern void
2978db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    IXAEngine_init(void *);
2988db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
299a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#if !(USE_PROFILES & USE_PROFILES_MUSIC)
300a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IDynamicSource_init         NULL
301a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IMetadataExtraction_init    NULL
302a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IMetadataTraversal_init     NULL
303a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IVisualization_init         NULL
304a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#endif
305a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten
306a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#if !(USE_PROFILES & USE_PROFILES_GAME)
307a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define I3DCommit_init      NULL
308a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define I3DDoppler_init     NULL
309a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define I3DGrouping_init    NULL
310a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define I3DLocation_init    NULL
311a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define I3DMacroscopic_init NULL
312a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define I3DSource_init      NULL
313a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IMIDIMessage_init   NULL
314a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IMIDIMuteSolo_init  NULL
315a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IMIDITempo_init     NULL
316a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IMIDITime_init      NULL
317a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IPitch_init         NULL
318a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IRatePitch_init     NULL
319a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define I3DGrouping_deinit  NULL
320a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#endif
321a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten
322a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#if !(USE_PROFILES & USE_PROFILES_BASE)
323a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IAudioDecoderCapabilities_init   NULL
324a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IAudioEncoderCapabilities_init   NULL
325a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IAudioEncoder_init               NULL
326a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IAudioIODeviceCapabilities_init  NULL
327a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IDeviceVolume_init               NULL
328a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IEngineCapabilities_init         NULL
329a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IThreadSync_init                 NULL
330a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten#define IThreadSync_deinit               NULL
331a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#endif
332a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten
333a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#if !(USE_PROFILES & USE_PROFILES_OPTIONAL)
334a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define ILEDArray_init  NULL
335a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IVibra_init     NULL
336a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#endif
337a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten
338a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#ifndef ANDROID
339a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten#define IAndroidConfiguration_init        NULL
340a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten#define IAndroidEffect_init               NULL
341a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten#define IAndroidEffectCapabilities_init   NULL
342a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten#define IAndroidEffectSend_init           NULL
343a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten#define IAndroidEffect_deinit             NULL
344a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten#define IAndroidEffectCapabilities_deinit NULL
345a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten#define IAndroidEffectCapabilities_Expose NULL
346fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi#define IAndroidBufferQueue_init          NULL
347a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#endif
348a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten
349a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#ifndef USE_OUTPUTMIXEXT
350a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IOutputMixExt_init  NULL
351a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#endif
352a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten
353e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten
35461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten/*static*/ const struct MPH_init MPH_init_table[MPH_MAX] = {
355711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_3DCOMMIT, */ I3DCommit_init, NULL, NULL, NULL, NULL },
356711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_3DDOPPLER, */ I3DDoppler_init, NULL, NULL, NULL, NULL },
357711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_3DGROUPING, */ I3DGrouping_init, NULL, I3DGrouping_deinit, NULL, NULL },
358711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_3DLOCATION, */ I3DLocation_init, NULL, NULL, NULL, NULL },
359711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_3DMACROSCOPIC, */ I3DMacroscopic_init, NULL, NULL, NULL, NULL },
360711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_3DSOURCE, */ I3DSource_init, NULL, NULL, NULL, NULL },
361711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_AUDIODECODERCAPABILITIES, */ IAudioDecoderCapabilities_init, NULL, NULL, NULL, NULL },
362711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_AUDIOENCODER, */ IAudioEncoder_init, NULL, NULL, NULL, NULL },
363711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_AUDIOENCODERCAPABILITIES, */ IAudioEncoderCapabilities_init, NULL, NULL, NULL, NULL },
364711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_AUDIOIODEVICECAPABILITIES, */ IAudioIODeviceCapabilities_init, NULL, NULL, NULL,
365711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten        NULL },
366711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_BASSBOOST, */ IBassBoost_init, NULL, IBassBoost_deinit, IBassBoost_Expose, NULL },
367711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_BUFFERQUEUE, */ IBufferQueue_init, NULL, IBufferQueue_deinit, NULL, NULL },
368711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_DEVICEVOLUME, */ IDeviceVolume_init, NULL, NULL, NULL, NULL },
369711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_DYNAMICINTERFACEMANAGEMENT, */ IDynamicInterfaceManagement_init, NULL, NULL, NULL,
370711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten        NULL },
371711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_DYNAMICSOURCE, */ IDynamicSource_init, NULL, NULL, NULL, NULL },
372711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_EFFECTSEND, */ IEffectSend_init, NULL, NULL, NULL, NULL },
373711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_ENGINE, */ IEngine_init, NULL, IEngine_deinit, NULL, NULL },
374711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_ENGINECAPABILITIES, */ IEngineCapabilities_init, NULL, NULL, NULL, NULL },
375a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    { /* MPH_ENVIRONMENTALREVERB, */ IEnvironmentalReverb_init, NULL, IEnvironmentalReverb_deinit,
376711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten        IEnvironmentalReverb_Expose, NULL },
377711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_EQUALIZER, */ IEqualizer_init, NULL, IEqualizer_deinit, IEqualizer_Expose, NULL },
378711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_LED, */ ILEDArray_init, NULL, NULL, NULL, NULL },
379711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_METADATAEXTRACTION, */ IMetadataExtraction_init, NULL, NULL, NULL, NULL },
380711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_METADATATRAVERSAL, */ IMetadataTraversal_init, NULL, NULL, NULL, NULL },
381711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_MIDIMESSAGE, */ IMIDIMessage_init, NULL, NULL, NULL, NULL },
382711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_MIDITIME, */ IMIDITime_init, NULL, NULL, NULL, NULL },
383711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_MIDITEMPO, */ IMIDITempo_init, NULL, NULL, NULL, NULL },
384711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_MIDIMUTESOLO, */ IMIDIMuteSolo_init, NULL, NULL, NULL, NULL },
385711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_MUTESOLO, */ IMuteSolo_init, NULL, NULL, NULL, NULL },
386711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_NULL, */ NULL, NULL, NULL, NULL, NULL },
387711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_OBJECT, */ IObject_init, NULL, IObject_deinit, NULL, NULL },
388711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_OUTPUTMIX, */ IOutputMix_init, NULL, NULL, NULL, NULL },
389711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_PITCH, */ IPitch_init, NULL, NULL, NULL, NULL },
390711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_PLAY, */ IPlay_init, NULL, NULL, NULL, NULL },
391711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_PLAYBACKRATE, */ IPlaybackRate_init, NULL, NULL, NULL, NULL },
392711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_PREFETCHSTATUS, */ IPrefetchStatus_init, NULL, NULL, NULL, NULL },
393a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    { /* MPH_PRESETREVERB, */ IPresetReverb_init, NULL, IPresetReverb_deinit,
394711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten        IPresetReverb_Expose, NULL },
395711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_RATEPITCH, */ IRatePitch_init, NULL, NULL, NULL, NULL },
396711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_RECORD, */ IRecord_init, NULL, NULL, NULL, NULL },
397711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_SEEK, */ ISeek_init, NULL, NULL, NULL, NULL },
398711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_THREADSYNC, */ IThreadSync_init, NULL, IThreadSync_deinit, NULL, NULL },
399711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_VIBRA, */ IVibra_init, NULL, NULL, NULL, NULL },
400711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_VIRTUALIZER, */ IVirtualizer_init, NULL, IVirtualizer_deinit, IVirtualizer_Expose,
401711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten        NULL },
402711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_VISUALIZATION, */ IVisualization_init, NULL, NULL, NULL, NULL },
403711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_VOLUME, */ IVolume_init, NULL, NULL, NULL, NULL },
404b0ab2dee391dd2cb257faeaba252ee6ecccc5f03Glenn Kasten// Wilhelm desktop extended interfaces
405711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_OUTPUTMIXEXT, */ IOutputMixExt_init, NULL, NULL, NULL, NULL },
406b0ab2dee391dd2cb257faeaba252ee6ecccc5f03Glenn Kasten// Android API level 9 extended interfaces
407711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_ANDROIDEFFECT */ IAndroidEffect_init, NULL, IAndroidEffect_deinit, NULL, NULL },
408a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    { /* MPH_ANDROIDEFFECTCAPABILITIES */ IAndroidEffectCapabilities_init, NULL,
409711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten        IAndroidEffectCapabilities_deinit, IAndroidEffectCapabilities_Expose, NULL },
410711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_ANDROIDEFFECTSEND */ IAndroidEffectSend_init, NULL, NULL, NULL, NULL },
411711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_ANDROIDCONFIGURATION */ IAndroidConfiguration_init, NULL, NULL, NULL, NULL },
41228bc6b725c207fb8fbd618caea4aa127f35ce1e1Jean-Michel Trivi    { /* MPH_ANDROIDSIMPLEBUFFERQUEUE */ IBufferQueue_init /* alias */, NULL, NULL, NULL, NULL },
413b0ab2dee391dd2cb257faeaba252ee6ecccc5f03Glenn Kasten// Android API level 10 extended interfaces
414fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi    { /* MPH_ANDROIDBUFFERQUEUE */ IAndroidBufferQueue_init, NULL, NULL, NULL, NULL },
4158db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten// OpenMAX AL 1.0.1 interfaces
41694a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten    { /* MPH_XAENGINE */ IXAEngine_init, NULL, NULL, NULL, NULL },
41794a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten    { /* MPH_XAPLAY */ IPlay_init, NULL, NULL, NULL, NULL },
418bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten};
419bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4200b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
421e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten/** \brief Construct a new instance of the specified class, exposing selected interfaces */
422bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
423ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn KastenIObject *construct(const ClassTable *class__, unsigned exposedMask, SLEngineItf engine)
424bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
42572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IObject *this;
426f6f5ceb363286d5ebef2c2e70c8a5aa135d5d1eeGlenn Kasten    // Do not change this to malloc; we depend on the object being memset to zero
42772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    this = (IObject *) calloc(1, class__->mSize);
428bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    if (NULL != this) {
429a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten        SL_LOGV("construct %s at %p", class__->mName, this);
43072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        unsigned lossOfControlMask = 0;
431ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten        // a NULL engine means we are constructing the engine
43272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        IEngine *thisEngine = (IEngine *) engine;
433d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten        if (NULL == thisEngine) {
434b0ab2dee391dd2cb257faeaba252ee6ecccc5f03Glenn Kasten            // thisEngine = &((CEngine *) this)->mEngine;
435b0ab2dee391dd2cb257faeaba252ee6ecccc5f03Glenn Kasten            this->mEngine = (CEngine *) this;
436d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten        } else {
437b0ab2dee391dd2cb257faeaba252ee6ecccc5f03Glenn Kasten            this->mEngine = (CEngine *) thisEngine->mThis;
438ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten            interface_lock_exclusive(thisEngine);
439d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten            if (MAX_INSTANCE <= thisEngine->mInstanceCount) {
440f51dba65751107c930759938775b75531ec1f330Glenn Kasten                SL_LOGE("Too many objects");
441ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten                interface_unlock_exclusive(thisEngine);
442d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten                free(this);
443ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten                return NULL;
444ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten            }
445d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten            // pre-allocate a pending slot, but don't assign bit from mInstanceMask yet
446ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten            ++thisEngine->mInstanceCount;
447d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten            assert(((unsigned) ~0) != thisEngine->mInstanceMask);
448ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten            interface_unlock_exclusive(thisEngine);
449ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten            // const, no lock needed
450f51dba65751107c930759938775b75531ec1f330Glenn Kasten            if (thisEngine->mLossOfControlGlobal) {
451ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten                lossOfControlMask = ~0;
452f51dba65751107c930759938775b75531ec1f330Glenn Kasten            }
453ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten        }
45472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        this->mLossOfControlMask = lossOfControlMask;
455ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten        this->mClass = class__;
456bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        const struct iid_vtable *x = class__->mInterfaces;
457510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        SLuint8 *interfaceStateP = this->mInterfaceStates;
458510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        SLuint32 index;
459510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        for (index = 0; index < class__->mInterfaceCount; ++index, ++x, exposedMask >>= 1) {
460276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten            SLuint8 state;
461a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten            // initialize all interfaces with init hooks, even if not exposed
462a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten            const struct MPH_init *mi = &MPH_init_table[x->mMPH];
463a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten            VoidHook init = mi->mInit;
464a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten            if (NULL != init) {
46583f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten                void *self = (char *) this + x->mOffset;
466d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten                // IObject does not have an mThis, so [1] is not always defined
467f51dba65751107c930759938775b75531ec1f330Glenn Kasten                if (index) {
468d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten                    ((IObject **) self)[1] = this;
469f51dba65751107c930759938775b75531ec1f330Glenn Kasten                }
470a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten                // call the initialization hook
471a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten                (*init)(self);
472e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten                // IObject does not require a call to GetInterface
473f51dba65751107c930759938775b75531ec1f330Glenn Kasten                if (index) {
474711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten                    // This trickery invalidates the v-table until GetInterface
475e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten                    ((size_t *) self)[0] ^= ~0;
476f51dba65751107c930759938775b75531ec1f330Glenn Kasten                }
477a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten                // if interface is exposed, also call the optional expose hook
478a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten                BoolHook expose;
479a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten                state = (exposedMask & 1) && ((NULL == (expose = mi->mExpose)) || (*expose)(self)) ?
480a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten                        INTERFACE_EXPOSED : INTERFACE_INITIALIZED;
481a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten                // FIXME log or report to application if an expose hook on a
482a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten                // required explicit interface fails at creation time
483f51dba65751107c930759938775b75531ec1f330Glenn Kasten            } else {
484510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten                state = INTERFACE_UNINITIALIZED;
485f51dba65751107c930759938775b75531ec1f330Glenn Kasten            }
486510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            *interfaceStateP++ = state;
487bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        }
488f51dba65751107c930759938775b75531ec1f330Glenn Kasten        // note that the new object is not yet published; creator must call IObject_Publish
489bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    }
490bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return this;
491bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
492