sles.cpp revision 8db0b106cdce5f5216b1535492de7930ad738aed
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);
57b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    return this->mClass->mObjectID;
58b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten}
59b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten
600b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
61928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten/** \brief Acquire a strong reference to an object.
62928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten *  Check that object has the specified "object ID" (which is really a class ID) and is in the
63928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten *  realized state.  If so, then acquire a strong reference to it and return true.
64928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten *  Otherwise return false.
65928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten */
66928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten
67928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn KastenSLresult AcquireStrongRef(IObject *object, SLuint32 expectedObjectID)
68928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten{
69928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    if (NULL == object) {
70928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
71928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    }
72928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    // NTH additional validity checks on address here
73928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    SLresult result;
74928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    object_lock_exclusive(object);
75928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    SLuint32 actualObjectID = IObjectToObjectID(object);
76928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    if (expectedObjectID != actualObjectID) {
77928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten        SL_LOGE("object %p has object ID %lu but expected %lu", object, actualObjectID,
78928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten            expectedObjectID);
79928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
80928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    } else if (SL_OBJECT_STATE_REALIZED != object->mState) {
81928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten        SL_LOGE("object %p with object ID %lu is not realized", object, actualObjectID);
82928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten        result = SL_RESULT_PRECONDITIONS_VIOLATED;
83928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    } else {
84928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten        ++object->mStrongRefCount;
85928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten        result = SL_RESULT_SUCCESS;
86928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    }
87928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    object_unlock_exclusive(object);
88928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    return result;
89928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten}
90928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten
91928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten
92928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten/** \brief Release a strong reference to an object.
93928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten *  Entry condition: the object is locked.
94928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten *  Exit condition: the object is unlocked.
95928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten *  Finishes the destroy if needed.
96928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten */
97928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten
98928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kastenvoid ReleaseStrongRefAndUnlockExclusive(IObject *object)
99928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten{
100a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#ifdef USE_DEBUG
101928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    assert(pthread_equal(pthread_self(), object->mOwner));
102a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#endif
103928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    assert(0 < object->mStrongRefCount);
104928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    if ((0 == --object->mStrongRefCount) && (SL_OBJECT_STATE_DESTROYING == object->mState)) {
105928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten        // FIXME do the destroy here - merge with IDestroy
106928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten        // but can't do this until we move Destroy to the sync thread
107928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten        // as Destroy is now a blocking operation, and to avoid a race
108928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    } else {
109928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten        object_unlock_exclusive(object);
110928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    }
111928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten}
112928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten
113928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten
114928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten/** \brief Release a strong reference to an object.
115928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten *  Entry condition: the object is unlocked.
116928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten *  Exit condition: the object is unlocked.
117928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten *  Finishes the destroy if needed.
118928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten */
119928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten
120928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kastenvoid ReleaseStrongRef(IObject *object)
121928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten{
122928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    assert(NULL != object);
123928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    object_lock_exclusive(object);
124928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    ReleaseStrongRefAndUnlockExclusive(object);
125928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten}
126928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten
127928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten
128e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten/** \brief Convert POSIX pthread error code to OpenSL ES result code */
129d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten
130d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn KastenSLresult err_to_result(int err)
131d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten{
132f51dba65751107c930759938775b75531ec1f330Glenn Kasten    if (EAGAIN == err || ENOMEM == err) {
133d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten        return SL_RESULT_RESOURCE_ERROR;
134f51dba65751107c930759938775b75531ec1f330Glenn Kasten    }
135f51dba65751107c930759938775b75531ec1f330Glenn Kasten    if (0 != err) {
136d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten        return SL_RESULT_INTERNAL_ERROR;
137f51dba65751107c930759938775b75531ec1f330Glenn Kasten    }
138d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten    return SL_RESULT_SUCCESS;
139d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten}
140d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten
1410b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
142e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten/** \brief Check the interface IDs passed into a Create operation */
14329b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten
144ed46c29d6a09112dbbf584c82953f63289596fd6Glenn KastenSLresult checkInterfaces(const ClassTable *class__, SLuint32 numInterfaces,
145ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired, unsigned *pExposedMask)
146bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
147bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    assert(NULL != class__ && NULL != pExposedMask);
14801e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten    // Initially no interfaces are exposed
149bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    unsigned exposedMask = 0;
150bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    const struct iid_vtable *interfaces = class__->mInterfaces;
151bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLuint32 interfaceCount = class__->mInterfaceCount;
152bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLuint32 i;
15301e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten    // Expose all implicit interfaces
154bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    for (i = 0; i < interfaceCount; ++i) {
155bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        switch (interfaces[i].mInterface) {
156bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        case INTERFACE_IMPLICIT:
157104c000a6f36b871ca11e0394db1e5217f374cafGlenn Kasten        case INTERFACE_IMPLICIT_PREREALIZE:
158a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten            // there must be an initialization hook present
159a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten            if (NULL != MPH_init_table[interfaces[i].mMPH].mInit) {
160a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten                exposedMask |= 1 << i;
161a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten            }
162bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten            break;
1635e3b06982dbf1eae237cc74326e66d51d3cdd664Glenn Kasten        case INTERFACE_EXPLICIT:
1645e3b06982dbf1eae237cc74326e66d51d3cdd664Glenn Kasten        case INTERFACE_DYNAMIC:
1655e3b06982dbf1eae237cc74326e66d51d3cdd664Glenn Kasten        case INTERFACE_UNAVAILABLE:
1665e3b06982dbf1eae237cc74326e66d51d3cdd664Glenn Kasten        case INTERFACE_EXPLICIT_PREREALIZE:
1675e3b06982dbf1eae237cc74326e66d51d3cdd664Glenn Kasten            break;
168bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        default:
1695e3b06982dbf1eae237cc74326e66d51d3cdd664Glenn Kasten            assert(false);
170bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten            break;
171bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        }
172bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    }
173d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    if (0 < numInterfaces) {
174f51dba65751107c930759938775b75531ec1f330Glenn Kasten        if (NULL == pInterfaceIds || NULL == pInterfaceRequired) {
175d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten            return SL_RESULT_PARAMETER_INVALID;
176f51dba65751107c930759938775b75531ec1f330Glenn Kasten        }
177104c000a6f36b871ca11e0394db1e5217f374cafGlenn Kasten        bool anyRequiredButUnsupported = false;
17801e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten        // Loop for each requested interface
179d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten        for (i = 0; i < numInterfaces; ++i) {
180bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten            SLInterfaceID iid = pInterfaceIds[i];
181f51dba65751107c930759938775b75531ec1f330Glenn Kasten            if (NULL == iid) {
182bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten                return SL_RESULT_PARAMETER_INVALID;
183f51dba65751107c930759938775b75531ec1f330Glenn Kasten            }
18429b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            int MPH, index;
18529b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            if ((0 > (MPH = IID_to_MPH(iid))) ||
186a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten                    // there must be an initialization hook present
187a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten                    (NULL == MPH_init_table[MPH].mInit) ||
188104c000a6f36b871ca11e0394db1e5217f374cafGlenn Kasten                    (0 > (index = class__->mMPH_to_index[MPH])) ||
189104c000a6f36b871ca11e0394db1e5217f374cafGlenn Kasten                    (INTERFACE_UNAVAILABLE == interfaces[index].mInterface)) {
19001e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten                // Here if interface was not found, or is not available for this object type
191f51dba65751107c930759938775b75531ec1f330Glenn Kasten                if (pInterfaceRequired[i]) {
19201e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten                    // Application said it required the interface, so give up
19301e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten                    SL_LOGE("class %s interface %lu required but unavailable MPH=%d",
19401e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten                            class__->mName, i, MPH);
195104c000a6f36b871ca11e0394db1e5217f374cafGlenn Kasten                    anyRequiredButUnsupported = true;
196f51dba65751107c930759938775b75531ec1f330Glenn Kasten                }
197a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten                // Application said it didn't really need the interface, so ignore with warning
198a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten                SL_LOGW("class %s interface %lu requested but unavailable MPH=%d",
199a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten                        class__->mName, i, MPH);
200bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten                continue;
201bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten            }
20201e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten            // The requested interface was both found and available, so expose it
20329b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            exposedMask |= (1 << index);
20401e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten            // Note that we ignore duplicate requests, including equal and aliased IDs
205d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten        }
206104c000a6f36b871ca11e0394db1e5217f374cafGlenn Kasten        if (anyRequiredButUnsupported) {
207104c000a6f36b871ca11e0394db1e5217f374cafGlenn Kasten            return SL_RESULT_FEATURE_UNSUPPORTED;
208104c000a6f36b871ca11e0394db1e5217f374cafGlenn Kasten        }
209d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    }
210bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    *pExposedMask = exposedMask;
211d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    return SL_RESULT_SUCCESS;
212d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
213d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
2140b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
21561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten/* Interface initialization hooks */
2162045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
217a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kastenextern void
218a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    I3DCommit_init(void *),
219a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    I3DDoppler_init(void *),
220a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    I3DGrouping_init(void *),
221a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    I3DLocation_init(void *),
222a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    I3DMacroscopic_init(void *),
223a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    I3DSource_init(void *),
224a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten    IAndroidConfiguration_init(void *),
225a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IAndroidEffect_init(void *),
226a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten    IAndroidEffectCapabilities_init(void *),
227a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten    IAndroidEffectSend_init(void *),
22828bc6b725c207fb8fbd618caea4aa127f35ce1e1Jean-Michel Trivi    IAndroidStreamSource_init(void *),
22961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IAudioDecoderCapabilities_init(void *),
23061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IAudioEncoder_init(void *),
231a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IAudioEncoderCapabilities_init(void *),
23261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IAudioIODeviceCapabilities_init(void *),
233a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IBassBoost_init(void *),
2340b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IBufferQueue_init(void *),
23561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IDeviceVolume_init(void *),
23661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IDynamicInterfaceManagement_init(void *),
23761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IDynamicSource_init(void *),
23861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IEffectSend_init(void *),
2390b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IEngine_init(void *),
240a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IEngineCapabilities_init(void *),
241a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IEnvironmentalReverb_init(void *),
242a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IEqualizer_init(void *),
24361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    ILEDArray_init(void *),
2440b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IMIDIMessage_init(void *),
2450b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IMIDIMuteSolo_init(void *),
2460b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IMIDITempo_init(void *),
2470b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IMIDITime_init(void *),
24861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IMetadataExtraction_init(void *),
24961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IMetadataTraversal_init(void *),
25061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IMuteSolo_init(void *),
25161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IObject_init(void *),
2520b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IOutputMix_init(void *),
253a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IOutputMixExt_init(void *),
25461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IPitch_init(void *),
2550b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IPlay_init(void *),
25661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IPlaybackRate_init(void *),
25761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IPrefetchStatus_init(void *),
258a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IPresetReverb_init(void *),
25961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IRatePitch_init(void *),
26061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IRecord_init(void *),
2610b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    ISeek_init(void *),
26261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IThreadSync_init(void *),
26361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IVibra_init(void *),
264a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IVirtualizer_init(void *),
2650b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IVisualization_init(void *),
2660b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IVolume_init(void *);
267a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten
2684597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kastenextern void
269a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    I3DGrouping_deinit(void *),
270a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IAndroidEffect_deinit(void *),
271a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IAndroidEffectCapabilities_deinit(void *),
272a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IBassBoost_deinit(void *),
273a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IBufferQueue_deinit(void *),
274a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IEngine_deinit(void *),
275a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IEnvironmentalReverb_deinit(void *),
276a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IEqualizer_deinit(void *),
277a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IObject_deinit(void *),
278a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IPresetReverb_deinit(void *),
279a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IThreadSync_deinit(void *),
280a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IVirtualizer_deinit(void *);
281a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten
282a9a70a4451545034c9263dd55b181f2912534c37Glenn Kastenextern bool
283a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IAndroidEffectCapabilities_Expose(void *),
284a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IBassBoost_Expose(void *),
285a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IEnvironmentalReverb_Expose(void *),
286a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IEqualizer_Expose(void *),
287a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IPresetReverb_Expose(void *),
288a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IVirtualizer_Expose(void *);
289b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten
2908db0b106cdce5f5216b1535492de7930ad738aedGlenn Kastenextern void
2918db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    IXAEngine_init(void *);
2928db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
293a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#if !(USE_PROFILES & USE_PROFILES_MUSIC)
294a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IDynamicSource_init         NULL
295a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IMetadataExtraction_init    NULL
296a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IMetadataTraversal_init     NULL
297a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IVisualization_init         NULL
298a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#endif
299a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten
300a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#if !(USE_PROFILES & USE_PROFILES_GAME)
301a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define I3DCommit_init      NULL
302a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define I3DDoppler_init     NULL
303a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define I3DGrouping_init    NULL
304a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define I3DLocation_init    NULL
305a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define I3DMacroscopic_init NULL
306a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define I3DSource_init      NULL
307a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IMIDIMessage_init   NULL
308a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IMIDIMuteSolo_init  NULL
309a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IMIDITempo_init     NULL
310a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IMIDITime_init      NULL
311a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IPitch_init         NULL
312a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IRatePitch_init     NULL
313a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define I3DGrouping_deinit  NULL
314a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#endif
315a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten
316a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#if !(USE_PROFILES & USE_PROFILES_BASE)
317a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IAudioDecoderCapabilities_init   NULL
318a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IAudioEncoderCapabilities_init   NULL
319a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IAudioEncoder_init               NULL
320a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IAudioIODeviceCapabilities_init  NULL
321a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IDeviceVolume_init               NULL
322a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IEngineCapabilities_init         NULL
323a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IThreadSync_init                 NULL
324a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten#define IThreadSync_deinit               NULL
325a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#endif
326a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten
327a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#if !(USE_PROFILES & USE_PROFILES_OPTIONAL)
328a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define ILEDArray_init  NULL
329a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IVibra_init     NULL
330a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#endif
331a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten
332a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#ifndef ANDROID
333a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten#define IAndroidConfiguration_init        NULL
334a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten#define IAndroidEffect_init               NULL
335a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten#define IAndroidEffectCapabilities_init   NULL
336a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten#define IAndroidEffectSend_init           NULL
337a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten#define IAndroidEffect_deinit             NULL
338a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten#define IAndroidEffectCapabilities_deinit NULL
339a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten#define IAndroidEffectCapabilities_Expose NULL
340b0ab2dee391dd2cb257faeaba252ee6ecccc5f03Glenn Kasten#define IAndroidStreamSource_init         NULL
341a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#endif
342a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten
343a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#ifndef USE_OUTPUTMIXEXT
344a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IOutputMixExt_init  NULL
345a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#endif
346a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten
347e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten
34861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten/*static*/ const struct MPH_init MPH_init_table[MPH_MAX] = {
349711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_3DCOMMIT, */ I3DCommit_init, NULL, NULL, NULL, NULL },
350711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_3DDOPPLER, */ I3DDoppler_init, NULL, NULL, NULL, NULL },
351711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_3DGROUPING, */ I3DGrouping_init, NULL, I3DGrouping_deinit, NULL, NULL },
352711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_3DLOCATION, */ I3DLocation_init, NULL, NULL, NULL, NULL },
353711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_3DMACROSCOPIC, */ I3DMacroscopic_init, NULL, NULL, NULL, NULL },
354711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_3DSOURCE, */ I3DSource_init, NULL, NULL, NULL, NULL },
355711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_AUDIODECODERCAPABILITIES, */ IAudioDecoderCapabilities_init, NULL, NULL, NULL, NULL },
356711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_AUDIOENCODER, */ IAudioEncoder_init, NULL, NULL, NULL, NULL },
357711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_AUDIOENCODERCAPABILITIES, */ IAudioEncoderCapabilities_init, NULL, NULL, NULL, NULL },
358711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_AUDIOIODEVICECAPABILITIES, */ IAudioIODeviceCapabilities_init, NULL, NULL, NULL,
359711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten        NULL },
360711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_BASSBOOST, */ IBassBoost_init, NULL, IBassBoost_deinit, IBassBoost_Expose, NULL },
361711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_BUFFERQUEUE, */ IBufferQueue_init, NULL, IBufferQueue_deinit, NULL, NULL },
362711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_DEVICEVOLUME, */ IDeviceVolume_init, NULL, NULL, NULL, NULL },
363711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_DYNAMICINTERFACEMANAGEMENT, */ IDynamicInterfaceManagement_init, NULL, NULL, NULL,
364711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten        NULL },
365711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_DYNAMICSOURCE, */ IDynamicSource_init, NULL, NULL, NULL, NULL },
366711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_EFFECTSEND, */ IEffectSend_init, NULL, NULL, NULL, NULL },
367711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_ENGINE, */ IEngine_init, NULL, IEngine_deinit, NULL, NULL },
368711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_ENGINECAPABILITIES, */ IEngineCapabilities_init, NULL, NULL, NULL, NULL },
369a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    { /* MPH_ENVIRONMENTALREVERB, */ IEnvironmentalReverb_init, NULL, IEnvironmentalReverb_deinit,
370711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten        IEnvironmentalReverb_Expose, NULL },
371711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_EQUALIZER, */ IEqualizer_init, NULL, IEqualizer_deinit, IEqualizer_Expose, NULL },
372711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_LED, */ ILEDArray_init, NULL, NULL, NULL, NULL },
373711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_METADATAEXTRACTION, */ IMetadataExtraction_init, NULL, NULL, NULL, NULL },
374711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_METADATATRAVERSAL, */ IMetadataTraversal_init, NULL, NULL, NULL, NULL },
375711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_MIDIMESSAGE, */ IMIDIMessage_init, NULL, NULL, NULL, NULL },
376711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_MIDITIME, */ IMIDITime_init, NULL, NULL, NULL, NULL },
377711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_MIDITEMPO, */ IMIDITempo_init, NULL, NULL, NULL, NULL },
378711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_MIDIMUTESOLO, */ IMIDIMuteSolo_init, NULL, NULL, NULL, NULL },
379711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_MUTESOLO, */ IMuteSolo_init, NULL, NULL, NULL, NULL },
380711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_NULL, */ NULL, NULL, NULL, NULL, NULL },
381711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_OBJECT, */ IObject_init, NULL, IObject_deinit, NULL, NULL },
382711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_OUTPUTMIX, */ IOutputMix_init, NULL, NULL, NULL, NULL },
383711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_PITCH, */ IPitch_init, NULL, NULL, NULL, NULL },
384711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_PLAY, */ IPlay_init, NULL, NULL, NULL, NULL },
385711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_PLAYBACKRATE, */ IPlaybackRate_init, NULL, NULL, NULL, NULL },
386711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_PREFETCHSTATUS, */ IPrefetchStatus_init, NULL, NULL, NULL, NULL },
387a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    { /* MPH_PRESETREVERB, */ IPresetReverb_init, NULL, IPresetReverb_deinit,
388711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten        IPresetReverb_Expose, NULL },
389711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_RATEPITCH, */ IRatePitch_init, NULL, NULL, NULL, NULL },
390711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_RECORD, */ IRecord_init, NULL, NULL, NULL, NULL },
391711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_SEEK, */ ISeek_init, NULL, NULL, NULL, NULL },
392711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_THREADSYNC, */ IThreadSync_init, NULL, IThreadSync_deinit, NULL, NULL },
393711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_VIBRA, */ IVibra_init, NULL, NULL, NULL, NULL },
394711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_VIRTUALIZER, */ IVirtualizer_init, NULL, IVirtualizer_deinit, IVirtualizer_Expose,
395711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten        NULL },
396711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_VISUALIZATION, */ IVisualization_init, NULL, NULL, NULL, NULL },
397711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_VOLUME, */ IVolume_init, NULL, NULL, NULL, NULL },
398b0ab2dee391dd2cb257faeaba252ee6ecccc5f03Glenn Kasten// Wilhelm desktop extended interfaces
399711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_OUTPUTMIXEXT, */ IOutputMixExt_init, NULL, NULL, NULL, NULL },
400b0ab2dee391dd2cb257faeaba252ee6ecccc5f03Glenn Kasten// Android API level 9 extended interfaces
401711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_ANDROIDEFFECT */ IAndroidEffect_init, NULL, IAndroidEffect_deinit, NULL, NULL },
402a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    { /* MPH_ANDROIDEFFECTCAPABILITIES */ IAndroidEffectCapabilities_init, NULL,
403711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten        IAndroidEffectCapabilities_deinit, IAndroidEffectCapabilities_Expose, NULL },
404711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_ANDROIDEFFECTSEND */ IAndroidEffectSend_init, NULL, NULL, NULL, NULL },
405711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_ANDROIDCONFIGURATION */ IAndroidConfiguration_init, NULL, NULL, NULL, NULL },
40628bc6b725c207fb8fbd618caea4aa127f35ce1e1Jean-Michel Trivi    { /* MPH_ANDROIDSIMPLEBUFFERQUEUE */ IBufferQueue_init /* alias */, NULL, NULL, NULL, NULL },
407b0ab2dee391dd2cb257faeaba252ee6ecccc5f03Glenn Kasten// Android API level 10 extended interfaces
408b0ab2dee391dd2cb257faeaba252ee6ecccc5f03Glenn Kasten    { /* MPH_ANDROIDSTREAMSOURCE */ IAndroidStreamSource_init, NULL, NULL, NULL, NULL },
4098db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten// OpenMAX AL 1.0.1 interfaces
4108db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    { /* MPHXA_ENGINE */ IXAEngine_init, NULL, NULL, NULL, NULL },
411bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten};
412bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
4130b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
414e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten/** \brief Construct a new instance of the specified class, exposing selected interfaces */
415bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
416ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn KastenIObject *construct(const ClassTable *class__, unsigned exposedMask, SLEngineItf engine)
417bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
41872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IObject *this;
419f6f5ceb363286d5ebef2c2e70c8a5aa135d5d1eeGlenn Kasten    // Do not change this to malloc; we depend on the object being memset to zero
42072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    this = (IObject *) calloc(1, class__->mSize);
421bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    if (NULL != this) {
422a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten        SL_LOGV("construct %s at %p", class__->mName, this);
42372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        unsigned lossOfControlMask = 0;
424ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten        // a NULL engine means we are constructing the engine
42572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        IEngine *thisEngine = (IEngine *) engine;
426d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten        if (NULL == thisEngine) {
427b0ab2dee391dd2cb257faeaba252ee6ecccc5f03Glenn Kasten            // thisEngine = &((CEngine *) this)->mEngine;
428b0ab2dee391dd2cb257faeaba252ee6ecccc5f03Glenn Kasten            this->mEngine = (CEngine *) this;
429d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten        } else {
430b0ab2dee391dd2cb257faeaba252ee6ecccc5f03Glenn Kasten            this->mEngine = (CEngine *) thisEngine->mThis;
431ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten            interface_lock_exclusive(thisEngine);
432d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten            if (MAX_INSTANCE <= thisEngine->mInstanceCount) {
433f51dba65751107c930759938775b75531ec1f330Glenn Kasten                SL_LOGE("Too many objects");
434ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten                interface_unlock_exclusive(thisEngine);
435d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten                free(this);
436ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten                return NULL;
437ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten            }
438d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten            // pre-allocate a pending slot, but don't assign bit from mInstanceMask yet
439ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten            ++thisEngine->mInstanceCount;
440d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten            assert(((unsigned) ~0) != thisEngine->mInstanceMask);
441ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten            interface_unlock_exclusive(thisEngine);
442ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten            // const, no lock needed
443f51dba65751107c930759938775b75531ec1f330Glenn Kasten            if (thisEngine->mLossOfControlGlobal) {
444ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten                lossOfControlMask = ~0;
445f51dba65751107c930759938775b75531ec1f330Glenn Kasten            }
446ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten        }
44772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        this->mLossOfControlMask = lossOfControlMask;
448ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten        this->mClass = class__;
449bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        const struct iid_vtable *x = class__->mInterfaces;
450510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        SLuint8 *interfaceStateP = this->mInterfaceStates;
451510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        SLuint32 index;
452510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        for (index = 0; index < class__->mInterfaceCount; ++index, ++x, exposedMask >>= 1) {
453276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten            SLuint8 state;
454a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten            // initialize all interfaces with init hooks, even if not exposed
455a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten            const struct MPH_init *mi = &MPH_init_table[x->mMPH];
456a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten            VoidHook init = mi->mInit;
457a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten            if (NULL != init) {
45883f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten                void *self = (char *) this + x->mOffset;
459d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten                // IObject does not have an mThis, so [1] is not always defined
460f51dba65751107c930759938775b75531ec1f330Glenn Kasten                if (index) {
461d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten                    ((IObject **) self)[1] = this;
462f51dba65751107c930759938775b75531ec1f330Glenn Kasten                }
463a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten                // call the initialization hook
464a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten                (*init)(self);
465e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten                // IObject does not require a call to GetInterface
466f51dba65751107c930759938775b75531ec1f330Glenn Kasten                if (index) {
467711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten                    // This trickery invalidates the v-table until GetInterface
468e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten                    ((size_t *) self)[0] ^= ~0;
469f51dba65751107c930759938775b75531ec1f330Glenn Kasten                }
470a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten                // if interface is exposed, also call the optional expose hook
471a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten                BoolHook expose;
472a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten                state = (exposedMask & 1) && ((NULL == (expose = mi->mExpose)) || (*expose)(self)) ?
473a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten                        INTERFACE_EXPOSED : INTERFACE_INITIALIZED;
474a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten                // FIXME log or report to application if an expose hook on a
475a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten                // required explicit interface fails at creation time
476f51dba65751107c930759938775b75531ec1f330Glenn Kasten            } else {
477510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten                state = INTERFACE_UNINITIALIZED;
478f51dba65751107c930759938775b75531ec1f330Glenn Kasten            }
479510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            *interfaceStateP++ = state;
480bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        }
481f51dba65751107c930759938775b75531ec1f330Glenn Kasten        // note that the new object is not yet published; creator must call IObject_Publish
482bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    }
483bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return this;
484bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
485