sles.cpp revision 28bc6b725c207fb8fbd618caea4aa127f35ce1e1
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
215e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten/** \brief Helper shared by decoder and encoder */
2160b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
217a438eb1cf1ae602afab00336528dd230bd929206Glenn KastenSLresult GetCodecCapabilities(SLuint32 codecId, SLuint32 *pIndex,
218369f3138f19f7102bf0f98b890ab84c8df633a93Glenn Kasten    SLAudioCodecDescriptor *pDescriptor, const CodecDescriptor *codecDescriptors)
219bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
220f51dba65751107c930759938775b75531ec1f330Glenn Kasten    if (NULL == pIndex) {
22161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
222f51dba65751107c930759938775b75531ec1f330Glenn Kasten    }
223369f3138f19f7102bf0f98b890ab84c8df633a93Glenn Kasten    const CodecDescriptor *cd = codecDescriptors;
22461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    SLuint32 index;
22561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    if (NULL == pDescriptor) {
226f51dba65751107c930759938775b75531ec1f330Glenn Kasten        for (index = 0 ; NULL != cd->mDescriptor; ++cd) {
227f51dba65751107c930759938775b75531ec1f330Glenn Kasten            if (cd->mCodecID == codecId) {
22861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten                ++index;
229f51dba65751107c930759938775b75531ec1f330Glenn Kasten            }
230f51dba65751107c930759938775b75531ec1f330Glenn Kasten        }
23161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        *pIndex = index;
23261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        return SL_RESULT_SUCCESS;
23361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    }
23461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    index = *pIndex;
23561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    for ( ; NULL != cd->mDescriptor; ++cd) {
236a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten        if (cd->mCodecID == codecId) {
23761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten            if (0 == index) {
23861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten                *pDescriptor = *cd->mDescriptor;
2397a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten#if 0   // Temporary workaround for Khronos bug 6331
240a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten                if (0 < pDescriptor->numSampleRatesSupported) {
2417a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten                    // The malloc is not in the 1.0.1 specification
242a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten                    SLmilliHertz *temp = (SLmilliHertz *) malloc(sizeof(SLmilliHertz) *
243a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten                        pDescriptor->numSampleRatesSupported);
244a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten                    assert(NULL != temp);
245a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten                    memcpy(temp, pDescriptor->pSampleRatesSupported, sizeof(SLmilliHertz) *
246a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten                        pDescriptor->numSampleRatesSupported);
247a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten                    pDescriptor->pSampleRatesSupported = temp;
248a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten                } else {
249a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten                    pDescriptor->pSampleRatesSupported = NULL;
250a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten                }
251a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten#endif
25261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten                return SL_RESULT_SUCCESS;
25361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten            }
25461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten            --index;
25561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        }
25661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    }
25761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    return SL_RESULT_PARAMETER_INVALID;
258bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
2592045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
260e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten
261e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten/** \brief Check a data locator and make local deep copy */
2620b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
263daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kastenstatic SLresult checkDataLocator(void *pLocator, DataLocator *pDataLocator)
264daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten{
265daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    if (NULL == pLocator) {
266a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten        pDataLocator->mLocatorType = SL_DATALOCATOR_NULL;
267daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        return SL_RESULT_SUCCESS;
268daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    }
269928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    SLresult result;
270daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    SLuint32 locatorType = *(SLuint32 *)pLocator;
271daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    switch (locatorType) {
272928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten
273daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    case SL_DATALOCATOR_ADDRESS:
274daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        pDataLocator->mAddress = *(SLDataLocator_Address *)pLocator;
275928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten        // if length is greater than zero, then the address must be non-NULL
276f51dba65751107c930759938775b75531ec1f330Glenn Kasten        if ((0 < pDataLocator->mAddress.length) && (NULL == pDataLocator->mAddress.pAddress)) {
277928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten            SL_LOGE("pAddress is NULL");
278daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            return SL_RESULT_PARAMETER_INVALID;
279928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten        }
280daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        break;
281928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten
282daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    case SL_DATALOCATOR_BUFFERQUEUE:
28301e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten#ifdef ANDROID
28401e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten    // This is an alias that is _not_ converted; the rest of the code must check for both locator
28501e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten    // types. That's because it is only an alias for audio players, not audio recorder objects
28601e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten    // so we have to remember the distinction.
28701e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten    case SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE:
28801e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten#endif
289daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        pDataLocator->mBufferQueue = *(SLDataLocator_BufferQueue *)pLocator;
2904b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten        // number of buffers must be specified, there is no default value, and must not be excessive
2914b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten        if (!((1 <= pDataLocator->mBufferQueue.numBuffers) &&
2924b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten            (pDataLocator->mBufferQueue.numBuffers <= 255))) {
2934b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten            SL_LOGE("numBuffers=%u", (unsigned) pDataLocator->mBufferQueue.numBuffers);
294daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            return SL_RESULT_PARAMETER_INVALID;
2954b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten        }
296daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        break;
297928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten
298daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    case SL_DATALOCATOR_IODEVICE:
299daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        {
300daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        pDataLocator->mIODevice = *(SLDataLocator_IODevice *)pLocator;
301daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        SLuint32 deviceType = pDataLocator->mIODevice.deviceType;
302928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten        SLObjectItf device = pDataLocator->mIODevice.device;
303928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten        if (NULL != device) {
304928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten            pDataLocator->mIODevice.deviceID = 0;
305928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten            SLuint32 expectedObjectID;
306928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten            switch (deviceType) {
307928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten            case SL_IODEVICE_LEDARRAY:
308928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten                expectedObjectID = SL_OBJECTID_LEDDEVICE;
309daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten                break;
310928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten            case SL_IODEVICE_VIBRA:
311928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten                expectedObjectID = SL_OBJECTID_VIBRADEVICE;
312daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten                break;
313928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten            // audio input and audio output cannot be specified via objects
314928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten            case SL_IODEVICE_AUDIOINPUT:
315928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten            // worse yet, an SL_IODEVICE enum constant for audio output does not exist yet
316928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten            // case SL_IODEVICE_AUDIOOUTPUT:
317daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            default:
318928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten                SL_LOGE("invalid deviceType %lu", deviceType);
319928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten                pDataLocator->mIODevice.device = NULL;
320daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten                return SL_RESULT_PARAMETER_INVALID;
321daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            }
322928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten            // check that device has the correct object ID and is realized,
323928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten            // and acquire a strong reference to it
324928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten            result = AcquireStrongRef((IObject *) device, expectedObjectID);
325928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten            if (SL_RESULT_SUCCESS != result) {
326928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten                SL_LOGE("locator type is IODEVICE, but device field %p has wrong object ID or is " \
327928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten                    "not realized", device);
328928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten                pDataLocator->mIODevice.device = NULL;
329928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten                return result;
330928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten            }
331daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        } else {
332928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten            SLuint32 deviceID = pDataLocator->mIODevice.deviceID;
333928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten            switch (deviceType) {
334928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten            case SL_IODEVICE_LEDARRAY:
335928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten                if (SL_DEFAULTDEVICEID_LED != deviceID) {
336928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten                    SL_LOGE("invalid LED deviceID %lu", deviceID);
337daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten                    return SL_RESULT_PARAMETER_INVALID;
338928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten                }
339daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten                break;
340928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten            case SL_IODEVICE_VIBRA:
341928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten                if (SL_DEFAULTDEVICEID_VIBRA != deviceID) {
342928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten                    SL_LOGE("invalid vibra deviceID %lu", deviceID);
343daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten                    return SL_RESULT_PARAMETER_INVALID;
344928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten                }
345daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten                break;
346928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten            case SL_IODEVICE_AUDIOINPUT:
347928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten                if (SL_DEFAULTDEVICEID_AUDIOINPUT != deviceID) {
348928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten                    SL_LOGE("invalid audio input deviceID %lu", deviceID);
349daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten                    return SL_RESULT_PARAMETER_INVALID;
350928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten                }
351daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten                break;
352daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            default:
353928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten                SL_LOGE("invalid deviceType %lu", deviceType);
354daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten                return SL_RESULT_PARAMETER_INVALID;
355daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            }
356daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        }
357daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        }
358daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        break;
359928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten
360daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    case SL_DATALOCATOR_MIDIBUFFERQUEUE:
361daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        pDataLocator->mMIDIBufferQueue = *(SLDataLocator_MIDIBufferQueue *)pLocator;
362f51dba65751107c930759938775b75531ec1f330Glenn Kasten        if (0 == pDataLocator->mMIDIBufferQueue.tpqn) {
363daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            pDataLocator->mMIDIBufferQueue.tpqn = 192;
364f51dba65751107c930759938775b75531ec1f330Glenn Kasten        }
3654b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten        // number of buffers must be specified, there is no default value, and must not be excessive
3664b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten        if (!((1 <= pDataLocator->mMIDIBufferQueue.numBuffers) &&
367928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten            (pDataLocator->mMIDIBufferQueue.numBuffers <= 255))) {
368928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten            SL_LOGE("invalid MIDI buffer queue");
3694b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten            return SL_RESULT_PARAMETER_INVALID;
370928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten        }
371daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        break;
372928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten
373daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    case SL_DATALOCATOR_OUTPUTMIX:
374daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        pDataLocator->mOutputMix = *(SLDataLocator_OutputMix *)pLocator;
375928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten        // check that output mix object has the correct object ID and is realized,
376928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten        // and acquire a strong reference to it
377928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten        result = AcquireStrongRef((IObject *) pDataLocator->mOutputMix.outputMix,
378928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten            SL_OBJECTID_OUTPUTMIX);
379928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten        if (SL_RESULT_SUCCESS != result) {
380928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten            SL_LOGE("locatorType is SL_DATALOCATOR_OUTPUTMIX, but outputMix field %p does not " \
381a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten                "refer to an SL_OBJECTID_OUTPUTMIX or the output mix is not realized", \
382928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten                pDataLocator->mOutputMix.outputMix);
383928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten            pDataLocator->mOutputMix.outputMix = NULL;
384928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten            return result;
3853d86d84fe89faa0efaf09bcbe4b841dfd3c7b5d8Glenn Kasten        }
386daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        break;
387928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten
388daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    case SL_DATALOCATOR_URI:
389daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        {
390daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        pDataLocator->mURI = *(SLDataLocator_URI *)pLocator;
391928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten        if (NULL == pDataLocator->mURI.URI) {
392928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten            SL_LOGE("invalid URI");
393daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            return SL_RESULT_PARAMETER_INVALID;
394928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten        }
395928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten        // NTH verify URI address for validity
396daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        size_t len = strlen((const char *) pDataLocator->mURI.URI);
397daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        SLchar *myURI = (SLchar *) malloc(len + 1);
398928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten        if (NULL == myURI) {
399928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten            pDataLocator->mURI.URI = NULL;
400daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            return SL_RESULT_MEMORY_FAILURE;
401928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten        }
402daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        memcpy(myURI, pDataLocator->mURI.URI, len + 1);
403daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        // Verify that another thread didn't change the NUL-terminator after we used it
404daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        // to determine length of string to copy. It's OK if the string became shorter.
405daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        if ('\0' != myURI[len]) {
406daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            free(myURI);
407928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten            pDataLocator->mURI.URI = NULL;
408daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            return SL_RESULT_PARAMETER_INVALID;
409daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        }
410daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        pDataLocator->mURI.URI = myURI;
411daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        }
412daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        break;
413928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten
414989ab369777ef514ac3ba6cdb893de9ae0c976bcJean-Michel Trivi#ifdef ANDROID
415989ab369777ef514ac3ba6cdb893de9ae0c976bcJean-Michel Trivi    case SL_DATALOCATOR_ANDROIDFD:
416989ab369777ef514ac3ba6cdb893de9ae0c976bcJean-Michel Trivi        {
417989ab369777ef514ac3ba6cdb893de9ae0c976bcJean-Michel Trivi        pDataLocator->mFD = *(SLDataLocator_AndroidFD *)pLocator;
4180b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten        SL_LOGV("Data locator FD: fd=%ld offset=%lld length=%lld", pDataLocator->mFD.fd,
419989ab369777ef514ac3ba6cdb893de9ae0c976bcJean-Michel Trivi                pDataLocator->mFD.offset, pDataLocator->mFD.length);
420928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten        // NTH check against process fd limit
421928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten        if (0 > pDataLocator->mFD.fd) {
422989ab369777ef514ac3ba6cdb893de9ae0c976bcJean-Michel Trivi            return SL_RESULT_PARAMETER_INVALID;
423989ab369777ef514ac3ba6cdb893de9ae0c976bcJean-Michel Trivi        }
424989ab369777ef514ac3ba6cdb893de9ae0c976bcJean-Michel Trivi        }
425989ab369777ef514ac3ba6cdb893de9ae0c976bcJean-Michel Trivi        break;
426989ab369777ef514ac3ba6cdb893de9ae0c976bcJean-Michel Trivi#endif
427928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten
428daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    default:
429928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten        SL_LOGE("invalid locatorType %lu", locatorType);
430daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
431daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    }
432928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten
433daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    // Verify that another thread didn't change the locatorType field after we used it
434daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    // to determine sizeof struct to copy.
435989ab369777ef514ac3ba6cdb893de9ae0c976bcJean-Michel Trivi    if (locatorType != pDataLocator->mLocatorType) {
436daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
437989ab369777ef514ac3ba6cdb893de9ae0c976bcJean-Michel Trivi    }
438daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    return SL_RESULT_SUCCESS;
439daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten}
440daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten
4410b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
442e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten/** \brief Free the local deep copy of a data locator */
4430b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
444daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kastenstatic void freeDataLocator(DataLocator *pDataLocator)
445daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten{
446daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    switch (pDataLocator->mLocatorType) {
447daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    case SL_DATALOCATOR_URI:
448928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten        if (NULL != pDataLocator->mURI.URI) {
449928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten            free(pDataLocator->mURI.URI);
450928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten            pDataLocator->mURI.URI = NULL;
451928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten        }
45200d2d554e04ac369367c903dbf53b975355d1bcdGlenn Kasten        pDataLocator->mURI.URI = NULL;
453daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        break;
454928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    case SL_DATALOCATOR_IODEVICE:
455928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten        if (NULL != pDataLocator->mIODevice.device) {
456928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten            ReleaseStrongRef((IObject *) pDataLocator->mIODevice.device);
457928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten            pDataLocator->mIODevice.device = NULL;
458928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten        }
459928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten        break;
460928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    case SL_DATALOCATOR_OUTPUTMIX:
461928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten        if (NULL != pDataLocator->mOutputMix.outputMix) {
462928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten            ReleaseStrongRef((IObject *) pDataLocator->mOutputMix.outputMix);
463928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten            pDataLocator->mOutputMix.outputMix = NULL;
464928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten        }
465928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten        break;
466daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    default:
467daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        break;
468daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    }
469daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten}
470daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten
4710b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
472e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten/** \brief Check a data format and make local deep copy */
4730b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
474daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kastenstatic SLresult checkDataFormat(void *pFormat, DataFormat *pDataFormat)
475daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten{
4760b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten    SLresult result = SL_RESULT_SUCCESS;
4770b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
478daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    if (NULL == pFormat) {
479a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten        pDataFormat->mFormatType = SL_DATAFORMAT_NULL;
4800b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten    } else {
4810b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten        SLuint32 formatType = *(SLuint32 *)pFormat;
4820b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten        switch (formatType) {
4830b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
4840b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten        case SL_DATAFORMAT_PCM:
4850b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten            pDataFormat->mPCM = *(SLDataFormat_PCM *)pFormat;
4860b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten            do {
4870b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
4880b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                // check the channel count
4890b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                switch (pDataFormat->mPCM.numChannels) {
4900b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                case 1:     // mono
4910b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                case 2:     // stereo
4920b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    break;
4930b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                case 0:     // unknown
4940b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    result = SL_RESULT_PARAMETER_INVALID;
4950b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    break;
4960b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                default:    // multi-channel
4970b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    result = SL_RESULT_CONTENT_UNSUPPORTED;
4980b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    break;
4990b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                }
5000b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                if (SL_RESULT_SUCCESS != result) {
5010b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    SL_LOGE("numChannels=%u", (unsigned) pDataFormat->mPCM.numChannels);
5020b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    break;
5030b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                }
5040b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
5050b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                // check the sampling rate
5060b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                switch (pDataFormat->mPCM.samplesPerSec) {
5070b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                case SL_SAMPLINGRATE_8:
5080b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                case SL_SAMPLINGRATE_11_025:
5090b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                case SL_SAMPLINGRATE_12:
5100b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                case SL_SAMPLINGRATE_16:
5110b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                case SL_SAMPLINGRATE_22_05:
5120b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                case SL_SAMPLINGRATE_24:
5130b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                case SL_SAMPLINGRATE_32:
5140b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                case SL_SAMPLINGRATE_44_1:
5150b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                case SL_SAMPLINGRATE_48:
5160b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                case SL_SAMPLINGRATE_64:
5170b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                case SL_SAMPLINGRATE_88_2:
5180b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                case SL_SAMPLINGRATE_96:
5190b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                case SL_SAMPLINGRATE_192:
5200b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    break;
5210b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                case 0:
5220b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    result = SL_RESULT_PARAMETER_INVALID;
5230b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    break;
5240b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                default:
5250b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    result = SL_RESULT_CONTENT_UNSUPPORTED;
5260b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    break;
5270b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                }
5280b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                if (SL_RESULT_SUCCESS != result) {
5290b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    SL_LOGE("samplesPerSec=%u", (unsigned) pDataFormat->mPCM.samplesPerSec);
5300b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    break;
5310b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                }
5320b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
5330b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                // check the sample bit depth
5340b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                switch (pDataFormat->mPCM.bitsPerSample) {
5350b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                case SL_PCMSAMPLEFORMAT_FIXED_8:
5360b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                case SL_PCMSAMPLEFORMAT_FIXED_16:
5370b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    break;
5380b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                case SL_PCMSAMPLEFORMAT_FIXED_20:
5390b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                case SL_PCMSAMPLEFORMAT_FIXED_24:
5400b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                case SL_PCMSAMPLEFORMAT_FIXED_28:
5410b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                case SL_PCMSAMPLEFORMAT_FIXED_32:
5420b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    result = SL_RESULT_CONTENT_UNSUPPORTED;
5430b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    break;
5440b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                default:
5450b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    result = SL_RESULT_PARAMETER_INVALID;
5460b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    break;
5470b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                }
5480b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                if (SL_RESULT_SUCCESS != result) {
5490b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    SL_LOGE("bitsPerSample=%u", (unsigned) pDataFormat->mPCM.bitsPerSample);
5500b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    break;
5510b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                }
5520b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
5530b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                // check the container bit depth
554dfbd7627912e9598b92e71346e47d91f9d14f44fGlenn Kasten                if (pDataFormat->mPCM.containerSize < pDataFormat->mPCM.bitsPerSample) {
555dfbd7627912e9598b92e71346e47d91f9d14f44fGlenn Kasten                    result = SL_RESULT_PARAMETER_INVALID;
556dfbd7627912e9598b92e71346e47d91f9d14f44fGlenn Kasten                } else if (pDataFormat->mPCM.containerSize != pDataFormat->mPCM.bitsPerSample) {
5570b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    result = SL_RESULT_CONTENT_UNSUPPORTED;
5580b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                }
5590b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                if (SL_RESULT_SUCCESS != result) {
560dfbd7627912e9598b92e71346e47d91f9d14f44fGlenn Kasten                    SL_LOGE("containerSize=%u, bitsPerSample=%u",
561dfbd7627912e9598b92e71346e47d91f9d14f44fGlenn Kasten                            (unsigned) pDataFormat->mPCM.containerSize,
562dfbd7627912e9598b92e71346e47d91f9d14f44fGlenn Kasten                            (unsigned) pDataFormat->mPCM.bitsPerSample);
5630b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    break;
5640b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                }
5650b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
5660b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                // check the channel mask
5670b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                switch (pDataFormat->mPCM.channelMask) {
5680b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                case SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT:
569f51dba65751107c930759938775b75531ec1f330Glenn Kasten                    if (2 != pDataFormat->mPCM.numChannels) {
5700b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                        result = SL_RESULT_PARAMETER_INVALID;
571f51dba65751107c930759938775b75531ec1f330Glenn Kasten                    }
5720b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    break;
5730b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                case SL_SPEAKER_FRONT_LEFT:
5740b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                case SL_SPEAKER_FRONT_RIGHT:
5750b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                case SL_SPEAKER_FRONT_CENTER:
576f51dba65751107c930759938775b75531ec1f330Glenn Kasten                    if (1 != pDataFormat->mPCM.numChannels) {
5770b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                        result = SL_RESULT_PARAMETER_INVALID;
578f51dba65751107c930759938775b75531ec1f330Glenn Kasten                    }
5790b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    break;
5800b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                case 0:
5810b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    pDataFormat->mPCM.channelMask = pDataFormat->mPCM.numChannels == 2 ?
5820b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                        SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT : SL_SPEAKER_FRONT_CENTER;
5830b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    break;
5840b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                default:
5850b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    result = SL_RESULT_PARAMETER_INVALID;
5860b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    break;
5870b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                }
5880b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                if (SL_RESULT_SUCCESS != result) {
589f51dba65751107c930759938775b75531ec1f330Glenn Kasten                    SL_LOGE("channelMask=0x%lx numChannels=%lu", pDataFormat->mPCM.channelMask,
590f51dba65751107c930759938775b75531ec1f330Glenn Kasten                        pDataFormat->mPCM.numChannels);
5910b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    break;
5920b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                }
5930b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
5940b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                // check the endianness / byte order
5950b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                switch (pDataFormat->mPCM.endianness) {
5960b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                case SL_BYTEORDER_LITTLEENDIAN:
5970b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                case SL_BYTEORDER_BIGENDIAN:
5980b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    break;
5994b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten                // native is proposed but not yet in spec
6000b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                default:
6010b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    result = SL_RESULT_PARAMETER_INVALID;
6020b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    break;
6030b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                }
6040b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                if (SL_RESULT_SUCCESS != result) {
6050b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    SL_LOGE("endianness=%u", (unsigned) pDataFormat->mPCM.endianness);
6060b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    break;
6070b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                }
6080b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
6090b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                // here if all checks passed successfully
6100b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
6110b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten            } while(0);
612daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            break;
6130b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
6140b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten        case SL_DATAFORMAT_MIME:
6150b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten            pDataFormat->mMIME = *(SLDataFormat_MIME *)pFormat;
6160b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten            if (NULL != pDataFormat->mMIME.mimeType) {
617928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten                // NTH check address for validity
6180b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                size_t len = strlen((const char *) pDataFormat->mMIME.mimeType);
6190b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                SLchar *myMIME = (SLchar *) malloc(len + 1);
6200b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                if (NULL == myMIME) {
6210b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    result = SL_RESULT_MEMORY_FAILURE;
6220b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                } else {
6230b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    memcpy(myMIME, pDataFormat->mMIME.mimeType, len + 1);
6240b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    // make sure MIME string was not modified asynchronously
6250b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    if ('\0' != myMIME[len]) {
6260b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                        free(myMIME);
627928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten                        myMIME = NULL;
6280b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                        result = SL_RESULT_PRECONDITIONS_VIOLATED;
6290b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    }
6300b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                }
631928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten                pDataFormat->mMIME.mimeType = myMIME;
6320b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten            }
633daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            break;
6340b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
635daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        default:
6360b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten            result = SL_RESULT_PARAMETER_INVALID;
6370b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten            SL_LOGE("formatType=%u", (unsigned) formatType);
638daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            break;
6390b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
640daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        }
6410b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
6420b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten        // make sure format type was not modified asynchronously
643f51dba65751107c930759938775b75531ec1f330Glenn Kasten        if ((SL_RESULT_SUCCESS == result) && (formatType != pDataFormat->mFormatType)) {
6440b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten            result = SL_RESULT_PRECONDITIONS_VIOLATED;
645f51dba65751107c930759938775b75531ec1f330Glenn Kasten        }
6460b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
647daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    }
6480b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
6490b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten    return result;
650daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten}
651daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten
6520b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
653e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten/** \brief Check interface ID compatibility with respect to a particular data locator format */
6540b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
6553c170255cc71942f310b676d968cf73328aa5d70Jean-Michel TriviSLresult checkSourceFormatVsInterfacesCompatibility(const DataLocatorFormat *pDataLocatorFormat,
656104c000a6f36b871ca11e0394db1e5217f374cafGlenn Kasten        const ClassTable *class__, unsigned exposedMask) {
657711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    int index;
65801e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten    switch (pDataLocatorFormat->mLocator.mLocatorType) {
65901e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten    case SL_DATALOCATOR_BUFFERQUEUE:
66001e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten#ifdef ANDROID
66101e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten    case SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE:
66201e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten#endif
663104c000a6f36b871ca11e0394db1e5217f374cafGlenn Kasten        // can't request SLSeekItf if data source is a buffer queue
664711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten        index = class__->mMPH_to_index[MPH_SEEK];
665104c000a6f36b871ca11e0394db1e5217f374cafGlenn Kasten        if (0 <= index) {
666104c000a6f36b871ca11e0394db1e5217f374cafGlenn Kasten            if (exposedMask & (1 << index)) {
6670b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                SL_LOGE("can't request SL_IID_SEEK with a buffer queue data source");
6683c170255cc71942f310b676d968cf73328aa5d70Jean-Michel Trivi                return SL_RESULT_FEATURE_UNSUPPORTED;
6693c170255cc71942f310b676d968cf73328aa5d70Jean-Michel Trivi            }
670104c000a6f36b871ca11e0394db1e5217f374cafGlenn Kasten        }
671104c000a6f36b871ca11e0394db1e5217f374cafGlenn Kasten        // can't request SLMuteSoloItf if data source is a mono buffer queue
672104c000a6f36b871ca11e0394db1e5217f374cafGlenn Kasten        index = class__->mMPH_to_index[MPH_MUTESOLO];
673104c000a6f36b871ca11e0394db1e5217f374cafGlenn Kasten        if (0 <= index) {
674104c000a6f36b871ca11e0394db1e5217f374cafGlenn Kasten            if ((exposedMask & (1 << index)) &&
675f6f5ceb363286d5ebef2c2e70c8a5aa135d5d1eeGlenn Kasten                    (SL_DATAFORMAT_PCM == pDataLocatorFormat->mFormat.mFormatType) &&
676f6f5ceb363286d5ebef2c2e70c8a5aa135d5d1eeGlenn Kasten                    (1 == pDataLocatorFormat->mFormat.mPCM.numChannels)) {
677f6f5ceb363286d5ebef2c2e70c8a5aa135d5d1eeGlenn Kasten                SL_LOGE("can't request SL_IID_MUTESOLO with a mono buffer queue data source");
678f6f5ceb363286d5ebef2c2e70c8a5aa135d5d1eeGlenn Kasten                return SL_RESULT_FEATURE_UNSUPPORTED;
679f6f5ceb363286d5ebef2c2e70c8a5aa135d5d1eeGlenn Kasten            }
6803c170255cc71942f310b676d968cf73328aa5d70Jean-Michel Trivi        }
68101e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten        break;
68201e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten    default:
683711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten        // can't request SLBufferQueueItf or its alias SLAndroidSimpleBufferQueueItf
684711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten        // if the data source is not a buffer queue
685711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten        index = class__->mMPH_to_index[MPH_BUFFERQUEUE];
686711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten#ifdef ANDROID
687711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten        assert(index == class__->mMPH_to_index[MPH_ANDROIDSIMPLEBUFFERQUEUE]);
688711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten#endif
689711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten        if (0 <= index) {
690711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten            if (exposedMask & (1 << index)) {
691711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten                SL_LOGE("can't request SL_IID_BUFFERQUEUE "
692711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten#ifdef ANDROID
693711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten                        "or SL_IID_ANDROIDSIMPLEBUFFERQUEUE "
694711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten#endif
695711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten                        "with a non-buffer queue data source");
696711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten                return SL_RESULT_FEATURE_UNSUPPORTED;
697711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten            }
698711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten        }
69901e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten        break;
7003c170255cc71942f310b676d968cf73328aa5d70Jean-Michel Trivi    }
7013c170255cc71942f310b676d968cf73328aa5d70Jean-Michel Trivi    return SL_RESULT_SUCCESS;
7023c170255cc71942f310b676d968cf73328aa5d70Jean-Michel Trivi}
7033c170255cc71942f310b676d968cf73328aa5d70Jean-Michel Trivi
7040b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
705e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten/** \brief Free the local deep copy of a data format */
7060b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
707daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kastenstatic void freeDataFormat(DataFormat *pDataFormat)
708daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten{
709daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    switch (pDataFormat->mFormatType) {
710daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    case SL_DATAFORMAT_MIME:
711928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten        if (NULL != pDataFormat->mMIME.mimeType) {
712928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten            free(pDataFormat->mMIME.mimeType);
713928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten            pDataFormat->mMIME.mimeType = NULL;
714928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten        }
715daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        break;
716daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    default:
717daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        break;
718daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    }
719daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten}
720daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten
7210b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
722e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten/** \brief Check a data source and make local deep copy */
7230b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
724daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn KastenSLresult checkDataSource(const SLDataSource *pDataSrc, DataLocatorFormat *pDataLocatorFormat)
725daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten{
726928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    if (NULL == pDataSrc) {
727928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten        SL_LOGE("pDataSrc NULL");
728daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
729928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    }
730daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    SLDataSource myDataSrc = *pDataSrc;
731daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    SLresult result;
732daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    result = checkDataLocator(myDataSrc.pLocator, &pDataLocatorFormat->mLocator);
733928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    if (SL_RESULT_SUCCESS != result) {
734daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        return result;
735928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    }
736a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten    switch (pDataLocatorFormat->mLocator.mLocatorType) {
737928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten
738a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten    case SL_DATALOCATOR_URI:
739a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten    case SL_DATALOCATOR_ADDRESS:
740a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten    case SL_DATALOCATOR_BUFFERQUEUE:
741a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten    case SL_DATALOCATOR_MIDIBUFFERQUEUE:
742928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten#ifdef ANDROID
743928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    case SL_DATALOCATOR_ANDROIDFD:
74401e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten    case SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE:
745928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten#endif
746a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten        result = checkDataFormat(myDataSrc.pFormat, &pDataLocatorFormat->mFormat);
747a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten        if (SL_RESULT_SUCCESS != result) {
748a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten            freeDataLocator(&pDataLocatorFormat->mLocator);
749a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten            return result;
750a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten        }
751a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten        break;
752928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten
753a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten    case SL_DATALOCATOR_NULL:
754a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten    case SL_DATALOCATOR_OUTPUTMIX:
755a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten    default:
756a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten        // invalid but fall through; the invalid locator will be caught later
7570b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten        SL_LOGE("mLocatorType=%u", (unsigned) pDataLocatorFormat->mLocator.mLocatorType);
7580b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten        // keep going
759928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten
760a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten    case SL_DATALOCATOR_IODEVICE:
761a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten        // for these data locator types, ignore the pFormat as it might be uninitialized
762a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten        pDataLocatorFormat->mFormat.mFormatType = SL_DATAFORMAT_NULL;
763a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten        break;
764daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    }
765928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten
766acd88797a1d3b8225bab888d29036e245f275be5Glenn Kasten    pDataLocatorFormat->u.mSource.pLocator = &pDataLocatorFormat->mLocator;
767acd88797a1d3b8225bab888d29036e245f275be5Glenn Kasten    pDataLocatorFormat->u.mSource.pFormat = &pDataLocatorFormat->mFormat;
768daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    return SL_RESULT_SUCCESS;
769daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten}
770daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten
7710b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
772e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten/** \brief Check a data sink and make local deep copy */
7730b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
774712b490060e4164fbe47986be1d2584d1610d8ddJean-Michel TriviSLresult checkDataSink(const SLDataSink *pDataSink, DataLocatorFormat *pDataLocatorFormat,
775712b490060e4164fbe47986be1d2584d1610d8ddJean-Michel Trivi        SLuint32 objType)
776daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten{
777928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    if (NULL == pDataSink) {
778928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten        SL_LOGE("pDataSink NULL");
779daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
780928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten    }
781daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    SLDataSink myDataSink = *pDataSink;
782daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    SLresult result;
783daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    result = checkDataLocator(myDataSink.pLocator, &pDataLocatorFormat->mLocator);
784712b490060e4164fbe47986be1d2584d1610d8ddJean-Michel Trivi    if (SL_RESULT_SUCCESS != result) {
785daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        return result;
786712b490060e4164fbe47986be1d2584d1610d8ddJean-Michel Trivi    }
787a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten    switch (pDataLocatorFormat->mLocator.mLocatorType) {
788712b490060e4164fbe47986be1d2584d1610d8ddJean-Michel Trivi
789a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten    case SL_DATALOCATOR_URI:
790a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten    case SL_DATALOCATOR_ADDRESS:
791a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten        result = checkDataFormat(myDataSink.pFormat, &pDataLocatorFormat->mFormat);
792a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten        if (SL_RESULT_SUCCESS != result) {
793a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten            freeDataLocator(&pDataLocatorFormat->mLocator);
794a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten            return result;
795a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten        }
796a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten        break;
797712b490060e4164fbe47986be1d2584d1610d8ddJean-Michel Trivi
798a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten    case SL_DATALOCATOR_BUFFERQUEUE:
79901e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten#ifdef ANDROID
80001e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten    case SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE:
80101e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten#endif
802712b490060e4164fbe47986be1d2584d1610d8ddJean-Michel Trivi        if (SL_OBJECTID_AUDIOPLAYER == objType) {
803928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten            SL_LOGE("buffer queue can't be used as data sink for audio player");
80401e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten            result = SL_RESULT_PARAMETER_INVALID;
805712b490060e4164fbe47986be1d2584d1610d8ddJean-Michel Trivi        } else if (SL_OBJECTID_AUDIORECORDER == objType) {
806712b490060e4164fbe47986be1d2584d1610d8ddJean-Michel Trivi#ifdef ANDROID
80701e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten            if (SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE !=
80801e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten                pDataLocatorFormat->mLocator.mLocatorType) {
80901e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten                SL_LOGE("audio recorder source locator must be SL_DATALOCATOR_ANDROIDBUFFERQUEUE");
81001e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten                result = SL_RESULT_PARAMETER_INVALID;
81101e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten            } else {
81201e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten                result = checkDataFormat(myDataSink.pFormat, &pDataLocatorFormat->mFormat);
813712b490060e4164fbe47986be1d2584d1610d8ddJean-Michel Trivi            }
814712b490060e4164fbe47986be1d2584d1610d8ddJean-Michel Trivi#else
815712b490060e4164fbe47986be1d2584d1610d8ddJean-Michel Trivi            SL_LOGE("mLocatorType=%u", (unsigned) pDataLocatorFormat->mLocator.mLocatorType);
81601e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten            result = SL_RESULT_PARAMETER_INVALID;
817712b490060e4164fbe47986be1d2584d1610d8ddJean-Michel Trivi#endif
818712b490060e4164fbe47986be1d2584d1610d8ddJean-Michel Trivi        }
81901e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten        if (SL_RESULT_SUCCESS != result) {
82001e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten            freeDataLocator(&pDataLocatorFormat->mLocator);
82101e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten            return result;
82201e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten        }
823712b490060e4164fbe47986be1d2584d1610d8ddJean-Michel Trivi        break;
824712b490060e4164fbe47986be1d2584d1610d8ddJean-Michel Trivi
825712b490060e4164fbe47986be1d2584d1610d8ddJean-Michel Trivi    case SL_DATALOCATOR_NULL:
826a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten    case SL_DATALOCATOR_MIDIBUFFERQUEUE:
827a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten    default:
828a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten        // invalid but fall through; the invalid locator will be caught later
8290b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten        SL_LOGE("mLocatorType=%u", (unsigned) pDataLocatorFormat->mLocator.mLocatorType);
8300b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten        // keep going
831928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten
832a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten    case SL_DATALOCATOR_IODEVICE:
833a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten    case SL_DATALOCATOR_OUTPUTMIX:
834a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten        // for these data locator types, ignore the pFormat as it might be uninitialized
835a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten        pDataLocatorFormat->mFormat.mFormatType = SL_DATAFORMAT_NULL;
836a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten        break;
837daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    }
838928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten
839acd88797a1d3b8225bab888d29036e245f275be5Glenn Kasten    pDataLocatorFormat->u.mSink.pLocator = &pDataLocatorFormat->mLocator;
840acd88797a1d3b8225bab888d29036e245f275be5Glenn Kasten    pDataLocatorFormat->u.mSink.pFormat = &pDataLocatorFormat->mFormat;
841daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    return SL_RESULT_SUCCESS;
842daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten}
843daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten
8440b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
845e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten/** \brief Free the local deep copy of a data locator format */
8460b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
847daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kastenvoid freeDataLocatorFormat(DataLocatorFormat *dlf)
848daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten{
849daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    freeDataLocator(&dlf->mLocator);
850daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    freeDataFormat(&dlf->mFormat);
851daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten}
852daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten
8530b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
85461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten/* Interface initialization hooks */
8552045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
856a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kastenextern void
857a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    I3DCommit_init(void *),
858a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    I3DDoppler_init(void *),
859a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    I3DGrouping_init(void *),
860a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    I3DLocation_init(void *),
861a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    I3DMacroscopic_init(void *),
862a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    I3DSource_init(void *),
863a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten    IAndroidConfiguration_init(void *),
864a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IAndroidEffect_init(void *),
865a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten    IAndroidEffectCapabilities_init(void *),
866a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten    IAndroidEffectSend_init(void *),
86728bc6b725c207fb8fbd618caea4aa127f35ce1e1Jean-Michel Trivi    IAndroidStreamSource_init(void *),
86861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IAudioDecoderCapabilities_init(void *),
86961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IAudioEncoder_init(void *),
870a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IAudioEncoderCapabilities_init(void *),
87161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IAudioIODeviceCapabilities_init(void *),
872a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IBassBoost_init(void *),
8730b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IBufferQueue_init(void *),
87461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IDeviceVolume_init(void *),
87561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IDynamicInterfaceManagement_init(void *),
87661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IDynamicSource_init(void *),
87761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IEffectSend_init(void *),
8780b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IEngine_init(void *),
879a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IEngineCapabilities_init(void *),
880a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IEnvironmentalReverb_init(void *),
881a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IEqualizer_init(void *),
88261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    ILEDArray_init(void *),
8830b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IMIDIMessage_init(void *),
8840b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IMIDIMuteSolo_init(void *),
8850b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IMIDITempo_init(void *),
8860b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IMIDITime_init(void *),
88761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IMetadataExtraction_init(void *),
88861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IMetadataTraversal_init(void *),
88961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IMuteSolo_init(void *),
89061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IObject_init(void *),
8910b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IOutputMix_init(void *),
892a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IOutputMixExt_init(void *),
89361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IPitch_init(void *),
8940b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IPlay_init(void *),
89561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IPlaybackRate_init(void *),
89661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IPrefetchStatus_init(void *),
897a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IPresetReverb_init(void *),
89861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IRatePitch_init(void *),
89961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IRecord_init(void *),
9000b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    ISeek_init(void *),
90161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IThreadSync_init(void *),
90261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IVibra_init(void *),
903a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IVirtualizer_init(void *),
9040b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IVisualization_init(void *),
9050b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IVolume_init(void *);
906a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten
9074597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kastenextern void
908a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    I3DGrouping_deinit(void *),
909a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IAndroidEffect_deinit(void *),
910a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IAndroidEffectCapabilities_deinit(void *),
911a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IBassBoost_deinit(void *),
912a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IBufferQueue_deinit(void *),
913a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IEngine_deinit(void *),
914a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IEnvironmentalReverb_deinit(void *),
915a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IEqualizer_deinit(void *),
916a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IObject_deinit(void *),
917a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IPresetReverb_deinit(void *),
918a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IThreadSync_deinit(void *),
919a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IVirtualizer_deinit(void *);
920a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten
921a9a70a4451545034c9263dd55b181f2912534c37Glenn Kastenextern bool
922a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IAndroidEffectCapabilities_Expose(void *),
923a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IBassBoost_Expose(void *),
924a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IEnvironmentalReverb_Expose(void *),
925a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IEqualizer_Expose(void *),
926a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IPresetReverb_Expose(void *),
927a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    IVirtualizer_Expose(void *);
928b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten
929a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#if !(USE_PROFILES & USE_PROFILES_MUSIC)
930a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IDynamicSource_init         NULL
931a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IMetadataExtraction_init    NULL
932a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IMetadataTraversal_init     NULL
933a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IVisualization_init         NULL
934a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#endif
935a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten
936a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#if !(USE_PROFILES & USE_PROFILES_GAME)
937a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define I3DCommit_init      NULL
938a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define I3DDoppler_init     NULL
939a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define I3DGrouping_init    NULL
940a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define I3DLocation_init    NULL
941a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define I3DMacroscopic_init NULL
942a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define I3DSource_init      NULL
943a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IMIDIMessage_init   NULL
944a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IMIDIMuteSolo_init  NULL
945a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IMIDITempo_init     NULL
946a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IMIDITime_init      NULL
947a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IPitch_init         NULL
948a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IRatePitch_init     NULL
949a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define I3DGrouping_deinit  NULL
950a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#endif
951a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten
952a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#if !(USE_PROFILES & USE_PROFILES_BASE)
953a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IAudioDecoderCapabilities_init   NULL
954a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IAudioEncoderCapabilities_init   NULL
955a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IAudioEncoder_init               NULL
956a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IAudioIODeviceCapabilities_init  NULL
957a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IDeviceVolume_init               NULL
958a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IEngineCapabilities_init         NULL
959a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IThreadSync_init                 NULL
960a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten#define IThreadSync_deinit               NULL
961a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#endif
962a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten
963a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#if !(USE_PROFILES & USE_PROFILES_OPTIONAL)
964a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define ILEDArray_init  NULL
965a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IVibra_init     NULL
966a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#endif
967a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten
968a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#ifndef ANDROID
969a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten#define IAndroidConfiguration_init        NULL
970a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten#define IAndroidEffect_init               NULL
971a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten#define IAndroidEffectCapabilities_init   NULL
972a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten#define IAndroidEffectSend_init           NULL
973a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten#define IAndroidEffect_deinit             NULL
974a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten#define IAndroidEffectCapabilities_deinit NULL
975a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten#define IAndroidEffectCapabilities_Expose NULL
976a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#endif
977a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten
978a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#ifndef USE_OUTPUTMIXEXT
979a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#define IOutputMixExt_init  NULL
980a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#endif
981a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten
982e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten
98361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten/*static*/ const struct MPH_init MPH_init_table[MPH_MAX] = {
984711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_3DCOMMIT, */ I3DCommit_init, NULL, NULL, NULL, NULL },
985711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_3DDOPPLER, */ I3DDoppler_init, NULL, NULL, NULL, NULL },
986711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_3DGROUPING, */ I3DGrouping_init, NULL, I3DGrouping_deinit, NULL, NULL },
987711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_3DLOCATION, */ I3DLocation_init, NULL, NULL, NULL, NULL },
988711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_3DMACROSCOPIC, */ I3DMacroscopic_init, NULL, NULL, NULL, NULL },
989711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_3DSOURCE, */ I3DSource_init, NULL, NULL, NULL, NULL },
990711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_AUDIODECODERCAPABILITIES, */ IAudioDecoderCapabilities_init, NULL, NULL, NULL, NULL },
991711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_AUDIOENCODER, */ IAudioEncoder_init, NULL, NULL, NULL, NULL },
992711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_AUDIOENCODERCAPABILITIES, */ IAudioEncoderCapabilities_init, NULL, NULL, NULL, NULL },
993711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_AUDIOIODEVICECAPABILITIES, */ IAudioIODeviceCapabilities_init, NULL, NULL, NULL,
994711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten        NULL },
995711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_BASSBOOST, */ IBassBoost_init, NULL, IBassBoost_deinit, IBassBoost_Expose, NULL },
996711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_BUFFERQUEUE, */ IBufferQueue_init, NULL, IBufferQueue_deinit, NULL, NULL },
997711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_DEVICEVOLUME, */ IDeviceVolume_init, NULL, NULL, NULL, NULL },
998711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_DYNAMICINTERFACEMANAGEMENT, */ IDynamicInterfaceManagement_init, NULL, NULL, NULL,
999711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten        NULL },
1000711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_DYNAMICSOURCE, */ IDynamicSource_init, NULL, NULL, NULL, NULL },
1001711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_EFFECTSEND, */ IEffectSend_init, NULL, NULL, NULL, NULL },
1002711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_ENGINE, */ IEngine_init, NULL, IEngine_deinit, NULL, NULL },
1003711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_ENGINECAPABILITIES, */ IEngineCapabilities_init, NULL, NULL, NULL, NULL },
1004a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    { /* MPH_ENVIRONMENTALREVERB, */ IEnvironmentalReverb_init, NULL, IEnvironmentalReverb_deinit,
1005711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten        IEnvironmentalReverb_Expose, NULL },
1006711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_EQUALIZER, */ IEqualizer_init, NULL, IEqualizer_deinit, IEqualizer_Expose, NULL },
1007711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_LED, */ ILEDArray_init, NULL, NULL, NULL, NULL },
1008711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_METADATAEXTRACTION, */ IMetadataExtraction_init, NULL, NULL, NULL, NULL },
1009711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_METADATATRAVERSAL, */ IMetadataTraversal_init, NULL, NULL, NULL, NULL },
1010711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_MIDIMESSAGE, */ IMIDIMessage_init, NULL, NULL, NULL, NULL },
1011711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_MIDITIME, */ IMIDITime_init, NULL, NULL, NULL, NULL },
1012711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_MIDITEMPO, */ IMIDITempo_init, NULL, NULL, NULL, NULL },
1013711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_MIDIMUTESOLO, */ IMIDIMuteSolo_init, NULL, NULL, NULL, NULL },
1014711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_MUTESOLO, */ IMuteSolo_init, NULL, NULL, NULL, NULL },
1015711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_NULL, */ NULL, NULL, NULL, NULL, NULL },
1016711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_OBJECT, */ IObject_init, NULL, IObject_deinit, NULL, NULL },
1017711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_OUTPUTMIX, */ IOutputMix_init, NULL, NULL, NULL, NULL },
1018711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_PITCH, */ IPitch_init, NULL, NULL, NULL, NULL },
1019711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_PLAY, */ IPlay_init, NULL, NULL, NULL, NULL },
1020711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_PLAYBACKRATE, */ IPlaybackRate_init, NULL, NULL, NULL, NULL },
1021711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_PREFETCHSTATUS, */ IPrefetchStatus_init, NULL, NULL, NULL, NULL },
1022a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    { /* MPH_PRESETREVERB, */ IPresetReverb_init, NULL, IPresetReverb_deinit,
1023711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten        IPresetReverb_Expose, NULL },
1024711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_RATEPITCH, */ IRatePitch_init, NULL, NULL, NULL, NULL },
1025711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_RECORD, */ IRecord_init, NULL, NULL, NULL, NULL },
1026711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_SEEK, */ ISeek_init, NULL, NULL, NULL, NULL },
1027711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_THREADSYNC, */ IThreadSync_init, NULL, IThreadSync_deinit, NULL, NULL },
1028711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_VIBRA, */ IVibra_init, NULL, NULL, NULL, NULL },
1029711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_VIRTUALIZER, */ IVirtualizer_init, NULL, IVirtualizer_deinit, IVirtualizer_Expose,
1030711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten        NULL },
1031711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_VISUALIZATION, */ IVisualization_init, NULL, NULL, NULL, NULL },
1032711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_VOLUME, */ IVolume_init, NULL, NULL, NULL, NULL },
1033711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_OUTPUTMIXEXT, */ IOutputMixExt_init, NULL, NULL, NULL, NULL },
1034711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_ANDROIDEFFECT */ IAndroidEffect_init, NULL, IAndroidEffect_deinit, NULL, NULL },
1035a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    { /* MPH_ANDROIDEFFECTCAPABILITIES */ IAndroidEffectCapabilities_init, NULL,
1036711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten        IAndroidEffectCapabilities_deinit, IAndroidEffectCapabilities_Expose, NULL },
1037711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_ANDROIDEFFECTSEND */ IAndroidEffectSend_init, NULL, NULL, NULL, NULL },
1038711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    { /* MPH_ANDROIDCONFIGURATION */ IAndroidConfiguration_init, NULL, NULL, NULL, NULL },
103928bc6b725c207fb8fbd618caea4aa127f35ce1e1Jean-Michel Trivi    { /* MPH_ANDROIDSIMPLEBUFFERQUEUE */ IBufferQueue_init /* alias */, NULL, NULL, NULL, NULL },
104028bc6b725c207fb8fbd618caea4aa127f35ce1e1Jean-Michel Trivi    { /* MPH_ANDROIDSTREAMSOURCE */ IAndroidStreamSource_init, NULL, NULL, NULL, NULL }
1041bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten};
1042bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
10430b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
1044e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten/** \brief Construct a new instance of the specified class, exposing selected interfaces */
1045bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
1046ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn KastenIObject *construct(const ClassTable *class__, unsigned exposedMask, SLEngineItf engine)
1047bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
104872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IObject *this;
1049f6f5ceb363286d5ebef2c2e70c8a5aa135d5d1eeGlenn Kasten    // Do not change this to malloc; we depend on the object being memset to zero
105072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    this = (IObject *) calloc(1, class__->mSize);
1051bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    if (NULL != this) {
1052a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten        SL_LOGV("construct %s at %p", class__->mName, this);
105372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        unsigned lossOfControlMask = 0;
1054ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten        // a NULL engine means we are constructing the engine
105572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        IEngine *thisEngine = (IEngine *) engine;
1056d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten        if (NULL == thisEngine) {
105772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten            thisEngine = &((CEngine *) this)->mEngine;
1058d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten        } else {
1059ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten            interface_lock_exclusive(thisEngine);
1060d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten            if (MAX_INSTANCE <= thisEngine->mInstanceCount) {
1061f51dba65751107c930759938775b75531ec1f330Glenn Kasten                SL_LOGE("Too many objects");
1062ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten                interface_unlock_exclusive(thisEngine);
1063d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten                free(this);
1064ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten                return NULL;
1065ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten            }
1066d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten            // pre-allocate a pending slot, but don't assign bit from mInstanceMask yet
1067ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten            ++thisEngine->mInstanceCount;
1068d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten            assert(((unsigned) ~0) != thisEngine->mInstanceMask);
1069ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten            interface_unlock_exclusive(thisEngine);
1070ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten            // const, no lock needed
1071f51dba65751107c930759938775b75531ec1f330Glenn Kasten            if (thisEngine->mLossOfControlGlobal) {
1072ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten                lossOfControlMask = ~0;
1073f51dba65751107c930759938775b75531ec1f330Glenn Kasten            }
1074ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten        }
107572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        this->mLossOfControlMask = lossOfControlMask;
1076ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten        this->mClass = class__;
1077ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten        this->mEngine = thisEngine;
1078bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        const struct iid_vtable *x = class__->mInterfaces;
1079510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        SLuint8 *interfaceStateP = this->mInterfaceStates;
1080510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        SLuint32 index;
1081510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        for (index = 0; index < class__->mInterfaceCount; ++index, ++x, exposedMask >>= 1) {
1082276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten            SLuint8 state;
1083a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten            // initialize all interfaces with init hooks, even if not exposed
1084a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten            const struct MPH_init *mi = &MPH_init_table[x->mMPH];
1085a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten            VoidHook init = mi->mInit;
1086a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten            if (NULL != init) {
108783f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten                void *self = (char *) this + x->mOffset;
1088d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten                // IObject does not have an mThis, so [1] is not always defined
1089f51dba65751107c930759938775b75531ec1f330Glenn Kasten                if (index) {
1090d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten                    ((IObject **) self)[1] = this;
1091f51dba65751107c930759938775b75531ec1f330Glenn Kasten                }
1092a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten                // call the initialization hook
1093a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten                (*init)(self);
1094e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten                // IObject does not require a call to GetInterface
1095f51dba65751107c930759938775b75531ec1f330Glenn Kasten                if (index) {
1096711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten                    // This trickery invalidates the v-table until GetInterface
1097e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten                    ((size_t *) self)[0] ^= ~0;
1098f51dba65751107c930759938775b75531ec1f330Glenn Kasten                }
1099a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten                // if interface is exposed, also call the optional expose hook
1100a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten                BoolHook expose;
1101a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten                state = (exposedMask & 1) && ((NULL == (expose = mi->mExpose)) || (*expose)(self)) ?
1102a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten                        INTERFACE_EXPOSED : INTERFACE_INITIALIZED;
1103a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten                // FIXME log or report to application if an expose hook on a
1104a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten                // required explicit interface fails at creation time
1105f51dba65751107c930759938775b75531ec1f330Glenn Kasten            } else {
1106510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten                state = INTERFACE_UNINITIALIZED;
1107f51dba65751107c930759938775b75531ec1f330Glenn Kasten            }
1108510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            *interfaceStateP++ = state;
1109bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        }
1110f51dba65751107c930759938775b75531ec1f330Glenn Kasten        // note that the new object is not yet published; creator must call IObject_Publish
1111bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    }
1112bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return this;
1113bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
1114bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
1115ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
1116711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten/* This implementation supports at most one engine */
1117711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten
1118711332800108ad6e0e594796e5f8db0da3eff402Glenn Kastenstatic CEngine *theOneTrueEngine = NULL;
1119711332800108ad6e0e594796e5f8db0da3eff402Glenn Kastenstatic pthread_mutex_t theOneTrueMutex = PTHREAD_MUTEX_INITIALIZER;
1120711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten
1121711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten
1122711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten/** \brief Called by dlopen when .so is loaded */
1123711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten
1124711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten__attribute__((constructor)) static void onDlOpen(void)
1125711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten{
1126711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten}
1127711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten
1128711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten
1129711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten/** \brief Called by dlclose when .so is unloaded */
1130711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten
1131711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten__attribute__((destructor)) static void onDlClose(void)
1132711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten{
1133711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    if (NULL != theOneTrueEngine) {
1134711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten        SL_LOGE("Object::Destroy omitted for engine %p", theOneTrueEngine);
1135711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    }
1136711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten}
1137711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten
1138711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten/** \brief Called by IObject::Destroy after engine is destroyed. The parameter refers to the
1139711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten *  previous engine, which is now undefined memory.
1140711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten */
1141711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten
1142711332800108ad6e0e594796e5f8db0da3eff402Glenn Kastenvoid CEngine_Destroyed(CEngine *self)
1143711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten{
1144711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    int ok;
1145711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    ok = pthread_mutex_lock(&theOneTrueMutex);
1146711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    assert(0 == ok);
1147711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    assert(self == theOneTrueEngine);
1148711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    theOneTrueEngine = NULL;
1149711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    ok = pthread_mutex_unlock(&theOneTrueMutex);
1150711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    assert(0 == ok);
1151711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten}
1152711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten
1153711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten
1154ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten/* Initial global entry points */
1155d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
11560b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
1157e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten/** \brief slCreateEngine Function */
11580b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
11590b167267bda99b68346045ccab14e810121d5de4Glenn KastenSLresult SLAPIENTRY slCreateEngine(SLObjectItf *pEngine, SLuint32 numOptions,
11600b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    const SLEngineOption *pEngineOptions, SLuint32 numInterfaces,
11610b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired)
1162d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
1163ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_ENTER_GLOBAL
1164ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
1165711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    int ok;
1166711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    ok = pthread_mutex_lock(&theOneTrueMutex);
1167711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    assert(0 == ok);
1168711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten
1169ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    do {
1170ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
1171ef8931ae547cd703e69df9ad350d69825da0f546Jean-Michel Trivi#ifdef ANDROID
1172ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        android::ProcessState::self()->startThreadPool();
117314e903028c4abfc1b2fbfab6560e3b864086f895Glenn Kasten#ifndef USE_BACKPORT
1174ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        android::DataSource::RegisterDefaultSniffers();
11756fff2c605cdc46a10037e011d8fb47702ae70c37Jean-Michel Trivi#endif
117614e903028c4abfc1b2fbfab6560e3b864086f895Glenn Kasten#endif
1177ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
1178ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        if (NULL == pEngine) {
1179ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            result = SL_RESULT_PARAMETER_INVALID;
1180ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            break;
1181ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        }
1182ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        *pEngine = NULL;
1183ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
1184b52bc98b576a9b56e82eca435849bd55e54b6bc1Glenn Kasten        if (NULL != theOneTrueEngine) {
1185b52bc98b576a9b56e82eca435849bd55e54b6bc1Glenn Kasten            SL_LOGE("slCreateEngine while another engine %p is active", theOneTrueEngine);
1186b52bc98b576a9b56e82eca435849bd55e54b6bc1Glenn Kasten            result = SL_RESULT_RESOURCE_ERROR;
1187b52bc98b576a9b56e82eca435849bd55e54b6bc1Glenn Kasten            break;
1188b52bc98b576a9b56e82eca435849bd55e54b6bc1Glenn Kasten        }
1189b52bc98b576a9b56e82eca435849bd55e54b6bc1Glenn Kasten
1190ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        if ((0 < numOptions) && (NULL == pEngineOptions)) {
1191928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten            SL_LOGE("numOptions=%lu and pEngineOptions=NULL", numOptions);
1192ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            result = SL_RESULT_PARAMETER_INVALID;
1193ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            break;
1194ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        }
1195ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
1196ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        // default values
1197ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        SLboolean threadSafe = SL_BOOLEAN_TRUE;
1198ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        SLboolean lossOfControlGlobal = SL_BOOLEAN_FALSE;
1199ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
1200ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        // process engine options
12010b167267bda99b68346045ccab14e810121d5de4Glenn Kasten        SLuint32 i;
12020b167267bda99b68346045ccab14e810121d5de4Glenn Kasten        const SLEngineOption *option = pEngineOptions;
1203ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        result = SL_RESULT_SUCCESS;
12040b167267bda99b68346045ccab14e810121d5de4Glenn Kasten        for (i = 0; i < numOptions; ++i, ++option) {
12050b167267bda99b68346045ccab14e810121d5de4Glenn Kasten            switch (option->feature) {
12060b167267bda99b68346045ccab14e810121d5de4Glenn Kasten            case SL_ENGINEOPTION_THREADSAFE:
12074b2f97bb1df6b3a65d2c3a158fba3a604c8f543cGlenn Kasten                threadSafe = SL_BOOLEAN_FALSE != (SLboolean) option->data; // normalize
12080b167267bda99b68346045ccab14e810121d5de4Glenn Kasten                break;
12090b167267bda99b68346045ccab14e810121d5de4Glenn Kasten            case SL_ENGINEOPTION_LOSSOFCONTROL:
12104b2f97bb1df6b3a65d2c3a158fba3a604c8f543cGlenn Kasten                lossOfControlGlobal = SL_BOOLEAN_FALSE != (SLboolean) option->data; // normalize
12110b167267bda99b68346045ccab14e810121d5de4Glenn Kasten                break;
12120b167267bda99b68346045ccab14e810121d5de4Glenn Kasten            default:
1213928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten                SL_LOGE("unknown engine option: feature=%lu data=%lu",
1214928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten                    option->feature, option->data);
1215ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                result = SL_RESULT_PARAMETER_INVALID;
1216ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                break;
12170b167267bda99b68346045ccab14e810121d5de4Glenn Kasten            }
12180b167267bda99b68346045ccab14e810121d5de4Glenn Kasten        }
1219928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten        if (SL_RESULT_SUCCESS != result) {
1220ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            break;
1221928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten        }
1222ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
1223ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        unsigned exposedMask;
1224ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        const ClassTable *pCEngine_class = objectIDtoClass(SL_OBJECTID_ENGINE);
1225c2b9d79c4b59caff965076f445f5a735a360b084Glenn Kasten        assert(NULL != pCEngine_class);
1226ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        result = checkInterfaces(pCEngine_class, numInterfaces,
1227ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            pInterfaceIds, pInterfaceRequired, &exposedMask);
1228928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten        if (SL_RESULT_SUCCESS != result) {
1229ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            break;
1230928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten        }
1231ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
1232ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        CEngine *this = (CEngine *) construct(pCEngine_class, exposedMask, NULL);
1233ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        if (NULL == this) {
1234ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            result = SL_RESULT_MEMORY_FAILURE;
1235ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            break;
1236ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        }
1237ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
1238a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten        // initialize fields not associated with an interface
1239a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten        memset(&this->mSyncThread, 0, sizeof(pthread_t));
1240a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten        // initialize fields related to an interface
1241ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        this->mObject.mLossOfControlMask = lossOfControlGlobal ? ~0 : 0;
1242ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        this->mEngine.mLossOfControlGlobal = lossOfControlGlobal;
1243ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        this->mEngineCapabilities.mThreadSafe = threadSafe;
1244104c000a6f36b871ca11e0394db1e5217f374cafGlenn Kasten        IObject_Publish(&this->mObject);
1245711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten        theOneTrueEngine = this;
1246104c000a6f36b871ca11e0394db1e5217f374cafGlenn Kasten        // return the new engine object
1247ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        *pEngine = &this->mObject.mItf;
1248ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
1249ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    } while(0);
1250ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
1251711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    ok = pthread_mutex_unlock(&theOneTrueMutex);
1252711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    assert(0 == ok);
1253711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten
1254ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_LEAVE_GLOBAL
1255d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
1256d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
1257ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
1258e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten/** \brief slQueryNumSupportedEngineInterfaces Function */
12590b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
1260ed46c29d6a09112dbbf584c82953f63289596fd6Glenn KastenSLresult SLAPIENTRY slQueryNumSupportedEngineInterfaces(SLuint32 *pNumSupportedInterfaces)
1261d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
1262ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_ENTER_GLOBAL
1263ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
1264ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    if (NULL == pNumSupportedInterfaces) {
1265ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
1266ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    } else {
12677a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten        const ClassTable *class__ = objectIDtoClass(SL_OBJECTID_ENGINE);
12687a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten        assert(NULL != class__);
12697a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten        SLuint32 count = 0;
12707a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten        SLuint32 i;
1271c3845706778edec308bd9ced559cec0a456608bdGlenn Kasten        for (i = 0; i < class__->mInterfaceCount; ++i) {
1272c3845706778edec308bd9ced559cec0a456608bdGlenn Kasten            switch (class__->mInterfaces[i].mInterface) {
1273c3845706778edec308bd9ced559cec0a456608bdGlenn Kasten            case INTERFACE_IMPLICIT:
1274104c000a6f36b871ca11e0394db1e5217f374cafGlenn Kasten            case INTERFACE_IMPLICIT_PREREALIZE:
1275c3845706778edec308bd9ced559cec0a456608bdGlenn Kasten            case INTERFACE_EXPLICIT:
12765e3b06982dbf1eae237cc74326e66d51d3cdd664Glenn Kasten            case INTERFACE_EXPLICIT_PREREALIZE:
1277c3845706778edec308bd9ced559cec0a456608bdGlenn Kasten            case INTERFACE_DYNAMIC:
12787a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten                ++count;
1279c3845706778edec308bd9ced559cec0a456608bdGlenn Kasten                break;
1280c3845706778edec308bd9ced559cec0a456608bdGlenn Kasten            case INTERFACE_UNAVAILABLE:
1281c3845706778edec308bd9ced559cec0a456608bdGlenn Kasten                break;
1282c3845706778edec308bd9ced559cec0a456608bdGlenn Kasten            default:
1283c3845706778edec308bd9ced559cec0a456608bdGlenn Kasten                assert(false);
1284c3845706778edec308bd9ced559cec0a456608bdGlenn Kasten                break;
1285c3845706778edec308bd9ced559cec0a456608bdGlenn Kasten            }
1286c3845706778edec308bd9ced559cec0a456608bdGlenn Kasten        }
12877a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten        *pNumSupportedInterfaces = count;
1288ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        result = SL_RESULT_SUCCESS;
1289ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    }
1290ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
1291ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_LEAVE_GLOBAL
1292d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
1293d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
1294ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
1295e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten/** \brief slQuerySupportedEngineInterfaces Function */
12960b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
1297ed46c29d6a09112dbbf584c82953f63289596fd6Glenn KastenSLresult SLAPIENTRY slQuerySupportedEngineInterfaces(SLuint32 index, SLInterfaceID *pInterfaceId)
1298d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
1299ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_ENTER_GLOBAL
1300ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
1301ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    if (NULL == pInterfaceId) {
1302ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
1303ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    } else {
13047a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten        *pInterfaceId = NULL;
13057a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten        const ClassTable *class__ = objectIDtoClass(SL_OBJECTID_ENGINE);
13067a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten        assert(NULL != class__);
13077a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten        result = SL_RESULT_PARAMETER_INVALID;   // will be reset later
13087a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten        SLuint32 i;
13097a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten        for (i = 0; i < class__->mInterfaceCount; ++i) {
1310c3845706778edec308bd9ced559cec0a456608bdGlenn Kasten            switch (class__->mInterfaces[i].mInterface) {
1311c3845706778edec308bd9ced559cec0a456608bdGlenn Kasten            case INTERFACE_IMPLICIT:
1312104c000a6f36b871ca11e0394db1e5217f374cafGlenn Kasten            case INTERFACE_IMPLICIT_PREREALIZE:
1313c3845706778edec308bd9ced559cec0a456608bdGlenn Kasten            case INTERFACE_EXPLICIT:
13145e3b06982dbf1eae237cc74326e66d51d3cdd664Glenn Kasten            case INTERFACE_EXPLICIT_PREREALIZE:
1315c3845706778edec308bd9ced559cec0a456608bdGlenn Kasten            case INTERFACE_DYNAMIC:
1316c3845706778edec308bd9ced559cec0a456608bdGlenn Kasten                break;
1317c3845706778edec308bd9ced559cec0a456608bdGlenn Kasten            case INTERFACE_UNAVAILABLE:
13187a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten                continue;
1319c3845706778edec308bd9ced559cec0a456608bdGlenn Kasten            default:
1320c3845706778edec308bd9ced559cec0a456608bdGlenn Kasten                assert(false);
1321c3845706778edec308bd9ced559cec0a456608bdGlenn Kasten                break;
1322c3845706778edec308bd9ced559cec0a456608bdGlenn Kasten            }
13237a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten            if (index == 0) {
132401e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten                // The engine has no aliases, but if it did, this would return only the primary
13257a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten                *pInterfaceId = &SL_IID_array[class__->mInterfaces[i].mMPH];
13267a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten                result = SL_RESULT_SUCCESS;
13277a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten                break;
13287a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten            }
13297a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten            --index;
1330ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        }
1331ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    }
1332ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
1333ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_LEAVE_GLOBAL
1334d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
1335