sles.cpp revision 4597a7427b697df31d0bbf4c2040806d0c27b6e0
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;
37e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten    if (0 > (index = class__->mMPH_to_index[MPH]))
38e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten        return false;
39e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten    assert(MAX_INDEX >= class__->mInterfaceCount);
40e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten    assert(class__->mInterfaceCount > (unsigned) index);
41e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten    switch (this->mInterfaceStates[index]) {
42e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten    case INTERFACE_EXPOSED:
43e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten    case INTERFACE_ADDED:
44e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten        return true;
45e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten    default:
46e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten        return false;
47e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten    }
48e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten}
49e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten
50e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten
51e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten/** \brief Map an IObject to it's "object ID" (which is really a class ID) */
52b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten
53b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn KastenSLuint32 IObjectToObjectID(IObject *this)
54b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten{
55b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    assert(NULL != this);
56b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    return this->mClass->mObjectID;
57b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten}
58b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten
590b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
60e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten/** \brief Convert POSIX pthread error code to OpenSL ES result code */
61d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten
62d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn KastenSLresult err_to_result(int err)
63d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten{
64d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten    if (EAGAIN == err || ENOMEM == err)
65d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten        return SL_RESULT_RESOURCE_ERROR;
66d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten    if (0 != err)
67d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten        return SL_RESULT_INTERNAL_ERROR;
68d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten    return SL_RESULT_SUCCESS;
69d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten}
70d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten
710b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
72e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten/** \brief Check the interface IDs passed into a Create operation */
7329b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten
74ed46c29d6a09112dbbf584c82953f63289596fd6Glenn KastenSLresult checkInterfaces(const ClassTable *class__, SLuint32 numInterfaces,
75ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired, unsigned *pExposedMask)
76bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
77bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    assert(NULL != class__ && NULL != pExposedMask);
78bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    unsigned exposedMask = 0;
79bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    const struct iid_vtable *interfaces = class__->mInterfaces;
80bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLuint32 interfaceCount = class__->mInterfaceCount;
81bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLuint32 i;
82bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    for (i = 0; i < interfaceCount; ++i) {
83bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        switch (interfaces[i].mInterface) {
84bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        case INTERFACE_IMPLICIT:
85bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten            exposedMask |= 1 << i;
86bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten            break;
87bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        default:
88bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten            break;
89bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        }
90bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    }
91d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    if (0 < numInterfaces) {
92d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten        if (NULL == pInterfaceIds || NULL == pInterfaceRequired)
93d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten            return SL_RESULT_PARAMETER_INVALID;
94d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten        for (i = 0; i < numInterfaces; ++i) {
95bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten            SLInterfaceID iid = pInterfaceIds[i];
96bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten            if (NULL == iid)
97bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten                return SL_RESULT_PARAMETER_INVALID;
9829b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            int MPH, index;
9929b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            if ((0 > (MPH = IID_to_MPH(iid))) ||
10029b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten                (0 > (index = class__->mMPH_to_index[MPH]))) {
101bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten                if (pInterfaceRequired[i])
102bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten                    return SL_RESULT_FEATURE_UNSUPPORTED;
103bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten                continue;
104bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten            }
10529b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            exposedMask |= (1 << index);
106d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten        }
107d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    }
108bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    *pExposedMask = exposedMask;
109d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    return SL_RESULT_SUCCESS;
110d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
111d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
1120b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
113e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten/** \brief Helper shared by decoder and encoder */
1140b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
115a438eb1cf1ae602afab00336528dd230bd929206Glenn KastenSLresult GetCodecCapabilities(SLuint32 codecId, SLuint32 *pIndex,
116369f3138f19f7102bf0f98b890ab84c8df633a93Glenn Kasten    SLAudioCodecDescriptor *pDescriptor, const CodecDescriptor *codecDescriptors)
117bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
11861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    if (NULL == pIndex)
11961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
120369f3138f19f7102bf0f98b890ab84c8df633a93Glenn Kasten    const CodecDescriptor *cd = codecDescriptors;
12161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    SLuint32 index;
12261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    if (NULL == pDescriptor) {
12361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        for (index = 0 ; NULL != cd->mDescriptor; ++cd)
124a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten            if (cd->mCodecID == codecId)
12561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten                ++index;
12661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        *pIndex = index;
12761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        return SL_RESULT_SUCCESS;
12861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    }
12961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    index = *pIndex;
13061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    for ( ; NULL != cd->mDescriptor; ++cd) {
131a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten        if (cd->mCodecID == codecId) {
13261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten            if (0 == index) {
13361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten                *pDescriptor = *cd->mDescriptor;
1347a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten#if 0   // Temporary workaround for Khronos bug 6331
135a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten                if (0 < pDescriptor->numSampleRatesSupported) {
1367a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten                    // The malloc is not in the 1.0.1 specification
137a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten                    SLmilliHertz *temp = (SLmilliHertz *) malloc(sizeof(SLmilliHertz) *
138a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten                        pDescriptor->numSampleRatesSupported);
139a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten                    assert(NULL != temp);
140a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten                    memcpy(temp, pDescriptor->pSampleRatesSupported, sizeof(SLmilliHertz) *
141a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten                        pDescriptor->numSampleRatesSupported);
142a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten                    pDescriptor->pSampleRatesSupported = temp;
143a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten                } else {
144a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten                    pDescriptor->pSampleRatesSupported = NULL;
145a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten                }
146a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten#endif
14761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten                return SL_RESULT_SUCCESS;
14861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten            }
14961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten            --index;
15061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        }
15161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    }
15261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    return SL_RESULT_PARAMETER_INVALID;
153bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
1542045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
155e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten
156e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten/** \brief Check a data locator and make local deep copy */
1570b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
158daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kastenstatic SLresult checkDataLocator(void *pLocator, DataLocator *pDataLocator)
159daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten{
160daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    if (NULL == pLocator) {
161a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten        pDataLocator->mLocatorType = SL_DATALOCATOR_NULL;
162daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        return SL_RESULT_SUCCESS;
163daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    }
164daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    SLuint32 locatorType = *(SLuint32 *)pLocator;
165daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    switch (locatorType) {
166daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    case SL_DATALOCATOR_ADDRESS:
167daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        pDataLocator->mAddress = *(SLDataLocator_Address *)pLocator;
168daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        if (0 < pDataLocator->mAddress.length && NULL == pDataLocator->mAddress.pAddress)
169daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            return SL_RESULT_PARAMETER_INVALID;
170daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        break;
171daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    case SL_DATALOCATOR_BUFFERQUEUE:
172daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        pDataLocator->mBufferQueue = *(SLDataLocator_BufferQueue *)pLocator;
1734b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten        // number of buffers must be specified, there is no default value, and must not be excessive
1744b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten        if (!((1 <= pDataLocator->mBufferQueue.numBuffers) &&
1754b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten            (pDataLocator->mBufferQueue.numBuffers <= 255))) {
1764b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten            SL_LOGE("numBuffers=%u", (unsigned) pDataLocator->mBufferQueue.numBuffers);
177daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            return SL_RESULT_PARAMETER_INVALID;
1784b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten        }
179daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        break;
180daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    case SL_DATALOCATOR_IODEVICE:
181daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        {
182daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        pDataLocator->mIODevice = *(SLDataLocator_IODevice *)pLocator;
183daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        SLuint32 deviceType = pDataLocator->mIODevice.deviceType;
184daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        if (NULL != pDataLocator->mIODevice.device) {
185daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            switch (IObjectToObjectID((IObject *) pDataLocator->mIODevice.device)) {
186daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            case SL_OBJECTID_LEDDEVICE:
187daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten                if (SL_IODEVICE_LEDARRAY != deviceType)
188daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten                    return SL_RESULT_PARAMETER_INVALID;
189daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten                break;
190daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            case SL_OBJECTID_VIBRADEVICE:
191daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten                if (SL_IODEVICE_VIBRA != deviceType)
192daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten                    return SL_RESULT_PARAMETER_INVALID;
193daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten                break;
194daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            default:
195daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten                return SL_RESULT_PARAMETER_INVALID;
196daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            }
197daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            pDataLocator->mIODevice.deviceID = 0;
198daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        } else {
199daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            switch (pDataLocator->mIODevice.deviceID) {
200daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            case SL_DEFAULTDEVICEID_LED:
201daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten                if (SL_IODEVICE_LEDARRAY != deviceType)
202daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten                    return SL_RESULT_PARAMETER_INVALID;
203daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten                break;
204daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            case SL_DEFAULTDEVICEID_VIBRA:
205daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten                if (SL_IODEVICE_VIBRA != deviceType)
206daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten                    return SL_RESULT_PARAMETER_INVALID;
207daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten                break;
208daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            case SL_DEFAULTDEVICEID_AUDIOINPUT:
209daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten                if (SL_IODEVICE_AUDIOINPUT != deviceType)
210daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten                    return SL_RESULT_PARAMETER_INVALID;
211daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten                break;
212daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            default:
213daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten                return SL_RESULT_PARAMETER_INVALID;
214daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            }
215daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        }
216daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        }
217daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        break;
218daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    case SL_DATALOCATOR_MIDIBUFFERQUEUE:
219daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        pDataLocator->mMIDIBufferQueue = *(SLDataLocator_MIDIBufferQueue *)pLocator;
220daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        if (0 == pDataLocator->mMIDIBufferQueue.tpqn)
221daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            pDataLocator->mMIDIBufferQueue.tpqn = 192;
2224b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten        // number of buffers must be specified, there is no default value, and must not be excessive
2234b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten        if (!((1 <= pDataLocator->mMIDIBufferQueue.numBuffers) &&
2244b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten            (pDataLocator->mMIDIBufferQueue.numBuffers <= 255)))
2254b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten            return SL_RESULT_PARAMETER_INVALID;
226daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        break;
227daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    case SL_DATALOCATOR_OUTPUTMIX:
2283d86d84fe89faa0efaf09bcbe4b841dfd3c7b5d8Glenn Kasten        {
229daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        pDataLocator->mOutputMix = *(SLDataLocator_OutputMix *)pLocator;
2303d86d84fe89faa0efaf09bcbe4b841dfd3c7b5d8Glenn Kasten        if (NULL == pDataLocator->mOutputMix.outputMix) {
2313d86d84fe89faa0efaf09bcbe4b841dfd3c7b5d8Glenn Kasten            SL_LOGE("locatorType is SL_DATALOCATOR_OUTPUTMIX, but outputMix field is NULL");
2323d86d84fe89faa0efaf09bcbe4b841dfd3c7b5d8Glenn Kasten            return SL_RESULT_PARAMETER_INVALID;
2333d86d84fe89faa0efaf09bcbe4b841dfd3c7b5d8Glenn Kasten        }
2343d86d84fe89faa0efaf09bcbe4b841dfd3c7b5d8Glenn Kasten        IObject *outputMixObject = (IObject *) pDataLocator->mOutputMix.outputMix;
2353d86d84fe89faa0efaf09bcbe4b841dfd3c7b5d8Glenn Kasten        if (SL_OBJECTID_OUTPUTMIX != IObjectToObjectID(outputMixObject)) {
2363d86d84fe89faa0efaf09bcbe4b841dfd3c7b5d8Glenn Kasten            SL_LOGE("locatorType is SL_DATALOCATOR_OUTPUTMIX, but outputMix field does not refer " \
2373d86d84fe89faa0efaf09bcbe4b841dfd3c7b5d8Glenn Kasten                "to an SL_OBJECTID_OUTPUTMIX");
238daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            return SL_RESULT_PARAMETER_INVALID;
2393d86d84fe89faa0efaf09bcbe4b841dfd3c7b5d8Glenn Kasten        }
2403d86d84fe89faa0efaf09bcbe4b841dfd3c7b5d8Glenn Kasten        if (outputMixObject->mState != SL_OBJECT_STATE_REALIZED) {
2413d86d84fe89faa0efaf09bcbe4b841dfd3c7b5d8Glenn Kasten            SL_LOGE("locatorType is SL_DATALOCATOR_OUTPUTMIX, but outputMix field refers to an " \
2423d86d84fe89faa0efaf09bcbe4b841dfd3c7b5d8Glenn Kasten                "unrealized SL_OBJECTID_OUTPUTMIX");
2433d86d84fe89faa0efaf09bcbe4b841dfd3c7b5d8Glenn Kasten            return SL_RESULT_PRECONDITIONS_VIOLATED;
2443d86d84fe89faa0efaf09bcbe4b841dfd3c7b5d8Glenn Kasten        }
2453d86d84fe89faa0efaf09bcbe4b841dfd3c7b5d8Glenn Kasten        // FIXME race condition as output mix could disappear, should atomically establish a link
2463d86d84fe89faa0efaf09bcbe4b841dfd3c7b5d8Glenn Kasten        }
247daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        break;
248daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    case SL_DATALOCATOR_URI:
249daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        {
250daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        pDataLocator->mURI = *(SLDataLocator_URI *)pLocator;
251daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        if (NULL == pDataLocator->mURI.URI)
252daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            return SL_RESULT_PARAMETER_INVALID;
253daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        size_t len = strlen((const char *) pDataLocator->mURI.URI);
254daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        SLchar *myURI = (SLchar *) malloc(len + 1);
255daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        if (NULL == myURI)
256daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            return SL_RESULT_MEMORY_FAILURE;
257daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        memcpy(myURI, pDataLocator->mURI.URI, len + 1);
258daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        // Verify that another thread didn't change the NUL-terminator after we used it
259daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        // to determine length of string to copy. It's OK if the string became shorter.
260daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        if ('\0' != myURI[len]) {
261daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            free(myURI);
262daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            return SL_RESULT_PARAMETER_INVALID;
263daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        }
264daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        pDataLocator->mURI.URI = myURI;
265daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        }
266daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        break;
267989ab369777ef514ac3ba6cdb893de9ae0c976bcJean-Michel Trivi#ifdef ANDROID
268989ab369777ef514ac3ba6cdb893de9ae0c976bcJean-Michel Trivi    case SL_DATALOCATOR_ANDROIDFD:
269989ab369777ef514ac3ba6cdb893de9ae0c976bcJean-Michel Trivi        {
270989ab369777ef514ac3ba6cdb893de9ae0c976bcJean-Michel Trivi        pDataLocator->mFD = *(SLDataLocator_AndroidFD *)pLocator;
2710b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten        SL_LOGV("Data locator FD: fd=%ld offset=%lld length=%lld", pDataLocator->mFD.fd,
272989ab369777ef514ac3ba6cdb893de9ae0c976bcJean-Michel Trivi                pDataLocator->mFD.offset, pDataLocator->mFD.length);
273989ab369777ef514ac3ba6cdb893de9ae0c976bcJean-Michel Trivi        if (-1 == pDataLocator->mFD.fd) {
274989ab369777ef514ac3ba6cdb893de9ae0c976bcJean-Michel Trivi            return SL_RESULT_PARAMETER_INVALID;
275989ab369777ef514ac3ba6cdb893de9ae0c976bcJean-Michel Trivi        }
276989ab369777ef514ac3ba6cdb893de9ae0c976bcJean-Michel Trivi        }
277989ab369777ef514ac3ba6cdb893de9ae0c976bcJean-Michel Trivi        break;
278989ab369777ef514ac3ba6cdb893de9ae0c976bcJean-Michel Trivi#endif
279daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    default:
280daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
281daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    }
282daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    // Verify that another thread didn't change the locatorType field after we used it
283daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    // to determine sizeof struct to copy.
284989ab369777ef514ac3ba6cdb893de9ae0c976bcJean-Michel Trivi    if (locatorType != pDataLocator->mLocatorType) {
285daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
286989ab369777ef514ac3ba6cdb893de9ae0c976bcJean-Michel Trivi    }
287daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    return SL_RESULT_SUCCESS;
288daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten}
289daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten
2900b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
291e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten/** \brief Free the local deep copy of a data locator */
2920b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
293daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kastenstatic void freeDataLocator(DataLocator *pDataLocator)
294daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten{
295daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    switch (pDataLocator->mLocatorType) {
296daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    case SL_DATALOCATOR_URI:
297daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        free(pDataLocator->mURI.URI);
29800d2d554e04ac369367c903dbf53b975355d1bcdGlenn Kasten        pDataLocator->mURI.URI = NULL;
299daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        break;
300daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    default:
301daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        break;
302daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    }
303daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten}
304daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten
3050b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
306e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten/** \brief Check a data format and make local deep copy */
3070b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
308daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kastenstatic SLresult checkDataFormat(void *pFormat, DataFormat *pDataFormat)
309daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten{
3100b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten    SLresult result = SL_RESULT_SUCCESS;
3110b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
312daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    if (NULL == pFormat) {
313a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten        pDataFormat->mFormatType = SL_DATAFORMAT_NULL;
3140b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten    } else {
3150b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten        SLuint32 formatType = *(SLuint32 *)pFormat;
3160b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten        switch (formatType) {
3170b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
3180b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten        case SL_DATAFORMAT_PCM:
3190b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten            pDataFormat->mPCM = *(SLDataFormat_PCM *)pFormat;
3200b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten            do {
3210b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
3220b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                // check the channel count
3230b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                switch (pDataFormat->mPCM.numChannels) {
3240b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                case 1:     // mono
3250b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                case 2:     // stereo
3260b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    break;
3270b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                case 0:     // unknown
3280b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    result = SL_RESULT_PARAMETER_INVALID;
3290b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    break;
3300b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                default:    // multi-channel
3310b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    result = SL_RESULT_CONTENT_UNSUPPORTED;
3320b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    break;
3330b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                }
3340b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                if (SL_RESULT_SUCCESS != result) {
3350b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    SL_LOGE("numChannels=%u", (unsigned) pDataFormat->mPCM.numChannels);
3360b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    break;
3370b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                }
3380b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
3390b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                // check the sampling rate
3400b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                switch (pDataFormat->mPCM.samplesPerSec) {
3410b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                case SL_SAMPLINGRATE_8:
3420b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                case SL_SAMPLINGRATE_11_025:
3430b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                case SL_SAMPLINGRATE_12:
3440b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                case SL_SAMPLINGRATE_16:
3450b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                case SL_SAMPLINGRATE_22_05:
3460b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                case SL_SAMPLINGRATE_24:
3470b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                case SL_SAMPLINGRATE_32:
3480b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                case SL_SAMPLINGRATE_44_1:
3490b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                case SL_SAMPLINGRATE_48:
3500b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                case SL_SAMPLINGRATE_64:
3510b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                case SL_SAMPLINGRATE_88_2:
3520b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                case SL_SAMPLINGRATE_96:
3530b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                case SL_SAMPLINGRATE_192:
3540b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    break;
3550b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                case 0:
3560b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    result = SL_RESULT_PARAMETER_INVALID;
3570b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    break;
3580b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                default:
3590b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    result = SL_RESULT_CONTENT_UNSUPPORTED;
3600b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    break;
3610b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                }
3620b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                if (SL_RESULT_SUCCESS != result) {
3630b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    SL_LOGE("samplesPerSec=%u", (unsigned) pDataFormat->mPCM.samplesPerSec);
3640b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    break;
3650b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                }
3660b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
3670b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                // check the sample bit depth
3680b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                switch (pDataFormat->mPCM.bitsPerSample) {
3690b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                case SL_PCMSAMPLEFORMAT_FIXED_8:
3700b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                case SL_PCMSAMPLEFORMAT_FIXED_16:
3710b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    break;
3720b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                case SL_PCMSAMPLEFORMAT_FIXED_20:
3730b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                case SL_PCMSAMPLEFORMAT_FIXED_24:
3740b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                case SL_PCMSAMPLEFORMAT_FIXED_28:
3750b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                case SL_PCMSAMPLEFORMAT_FIXED_32:
3760b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    result = SL_RESULT_CONTENT_UNSUPPORTED;
3770b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    break;
3780b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                default:
3790b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    result = SL_RESULT_PARAMETER_INVALID;
3800b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    break;
3810b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                }
3820b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                if (SL_RESULT_SUCCESS != result) {
3830b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    SL_LOGE("bitsPerSample=%u", (unsigned) pDataFormat->mPCM.bitsPerSample);
3840b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    break;
3850b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                }
3860b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
3870b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                // check the container bit depth
3880b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                switch (pDataFormat->mPCM.containerSize) {
3890b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                case SL_PCMSAMPLEFORMAT_FIXED_8:
3900b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                case SL_PCMSAMPLEFORMAT_FIXED_16:
3910b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    if (pDataFormat->mPCM.containerSize != pDataFormat->mPCM.bitsPerSample)
3920b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                        result = SL_RESULT_CONTENT_UNSUPPORTED;
3930b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    break;
3940b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                default:
3950b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    result = SL_RESULT_CONTENT_UNSUPPORTED;
3960b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    break;
3970b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                }
3980b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                if (SL_RESULT_SUCCESS != result) {
3990b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    SL_LOGE("containerSize=%u", (unsigned) pDataFormat->mPCM.containerSize);
4000b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    break;
4010b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                }
4020b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
4030b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                // check the channel mask
4040b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                switch (pDataFormat->mPCM.channelMask) {
4050b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                case SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT:
4060b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    if (2 != pDataFormat->mPCM.numChannels)
4070b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                        result = SL_RESULT_PARAMETER_INVALID;
4080b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    break;
4090b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                case SL_SPEAKER_FRONT_LEFT:
4100b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                case SL_SPEAKER_FRONT_RIGHT:
4110b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                case SL_SPEAKER_FRONT_CENTER:
4120b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    if (1 != pDataFormat->mPCM.numChannels)
4130b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                        result = SL_RESULT_PARAMETER_INVALID;
4140b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    break;
4150b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                case 0:
4160b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    pDataFormat->mPCM.channelMask = pDataFormat->mPCM.numChannels == 2 ?
4170b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                        SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT : SL_SPEAKER_FRONT_CENTER;
4180b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    break;
4190b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                default:
4200b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    result = SL_RESULT_PARAMETER_INVALID;
4210b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    break;
4220b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                }
4230b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                if (SL_RESULT_SUCCESS != result) {
4240b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    SL_LOGE("channelMask=%u", (unsigned) pDataFormat->mPCM.channelMask);
4250b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    break;
4260b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                }
4270b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
4280b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                // check the endianness / byte order
4290b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                switch (pDataFormat->mPCM.endianness) {
4300b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                case SL_BYTEORDER_LITTLEENDIAN:
4310b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                case SL_BYTEORDER_BIGENDIAN:
4320b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    break;
4334b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten                // native is proposed but not yet in spec
4340b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                default:
4350b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    result = SL_RESULT_PARAMETER_INVALID;
4360b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    break;
4370b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                }
4380b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                if (SL_RESULT_SUCCESS != result) {
4390b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    SL_LOGE("endianness=%u", (unsigned) pDataFormat->mPCM.endianness);
4400b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    break;
4410b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                }
4420b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
4430b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                // here if all checks passed successfully
4440b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
4450b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten            } while(0);
446daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            break;
4470b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
4480b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten        case SL_DATAFORMAT_MIME:
4490b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten            pDataFormat->mMIME = *(SLDataFormat_MIME *)pFormat;
4500b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten            if (NULL != pDataFormat->mMIME.mimeType) {
4510b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                size_t len = strlen((const char *) pDataFormat->mMIME.mimeType);
4520b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                SLchar *myMIME = (SLchar *) malloc(len + 1);
4530b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                if (NULL == myMIME) {
4540b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    result = SL_RESULT_MEMORY_FAILURE;
4550b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                } else {
4560b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    memcpy(myMIME, pDataFormat->mMIME.mimeType, len + 1);
4570b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    // make sure MIME string was not modified asynchronously
4580b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    if ('\0' != myMIME[len]) {
4590b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                        free(myMIME);
4600b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                        result = SL_RESULT_PRECONDITIONS_VIOLATED;
4610b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    }
4620b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                    pDataFormat->mMIME.mimeType = myMIME;
4630b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                }
4640b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten            }
465daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            break;
4660b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
467daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        default:
4680b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten            result = SL_RESULT_PARAMETER_INVALID;
4690b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten            SL_LOGE("formatType=%u", (unsigned) formatType);
470daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            break;
4710b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
472daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        }
4730b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
4740b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten        // make sure format type was not modified asynchronously
4750b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten        if (SL_RESULT_SUCCESS == result && formatType != pDataFormat->mFormatType)
4760b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten            result = SL_RESULT_PRECONDITIONS_VIOLATED;
4770b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
478daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    }
4790b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
4800b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten    return result;
481daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten}
482daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten
4830b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
484e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten/** \brief Check interface ID compatibility with respect to a particular data locator format */
4850b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
4863c170255cc71942f310b676d968cf73328aa5d70Jean-Michel TriviSLresult checkSourceFormatVsInterfacesCompatibility(const DataLocatorFormat *pDataLocatorFormat,
4873c170255cc71942f310b676d968cf73328aa5d70Jean-Michel Trivi        SLuint32 numInterfaces, const SLInterfaceID *pInterfaceIds,
4883c170255cc71942f310b676d968cf73328aa5d70Jean-Michel Trivi            const SLboolean *pInterfaceRequired) {
4893c170255cc71942f310b676d968cf73328aa5d70Jean-Michel Trivi    // can't request SLSeekItf if data source is a buffer queue
4903c170255cc71942f310b676d968cf73328aa5d70Jean-Michel Trivi    if (SL_DATALOCATOR_BUFFERQUEUE == pDataLocatorFormat->mLocator.mLocatorType) {
491a6b2d444f86f7bca8da33cb9904b225220b675a0Glenn Kasten        SLuint32 i;
492a6b2d444f86f7bca8da33cb9904b225220b675a0Glenn Kasten        for (i = 0; i < numInterfaces; i++) {
4933c170255cc71942f310b676d968cf73328aa5d70Jean-Michel Trivi            if (pInterfaceRequired[i] && (SL_IID_SEEK == pInterfaceIds[i])) {
4940b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten                SL_LOGE("can't request SL_IID_SEEK with a buffer queue data source");
4953c170255cc71942f310b676d968cf73328aa5d70Jean-Michel Trivi                return SL_RESULT_FEATURE_UNSUPPORTED;
4963c170255cc71942f310b676d968cf73328aa5d70Jean-Michel Trivi            }
4973c170255cc71942f310b676d968cf73328aa5d70Jean-Michel Trivi        }
4983c170255cc71942f310b676d968cf73328aa5d70Jean-Michel Trivi    }
4993c170255cc71942f310b676d968cf73328aa5d70Jean-Michel Trivi    return SL_RESULT_SUCCESS;
5003c170255cc71942f310b676d968cf73328aa5d70Jean-Michel Trivi}
5013c170255cc71942f310b676d968cf73328aa5d70Jean-Michel Trivi
5020b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
503e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten/** \brief Free the local deep copy of a data format */
5040b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
505daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kastenstatic void freeDataFormat(DataFormat *pDataFormat)
506daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten{
507daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    switch (pDataFormat->mFormatType) {
508daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    case SL_DATAFORMAT_MIME:
509daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        free(pDataFormat->mMIME.mimeType);
51000d2d554e04ac369367c903dbf53b975355d1bcdGlenn Kasten        pDataFormat->mMIME.mimeType = NULL;
511daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        break;
512daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    default:
513daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        break;
514daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    }
515daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten}
516daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten
5170b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
518e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten/** \brief Check a data source and make local deep copy */
5190b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
520daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn KastenSLresult checkDataSource(const SLDataSource *pDataSrc, DataLocatorFormat *pDataLocatorFormat)
521daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten{
522daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    if (NULL == pDataSrc)
523daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
524daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    SLDataSource myDataSrc = *pDataSrc;
525daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    SLresult result;
526daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    result = checkDataLocator(myDataSrc.pLocator, &pDataLocatorFormat->mLocator);
527daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    if (SL_RESULT_SUCCESS != result)
528daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        return result;
529a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten    switch (pDataLocatorFormat->mLocator.mLocatorType) {
530a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten    case SL_DATALOCATOR_URI:
531a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten    case SL_DATALOCATOR_ADDRESS:
532a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten    case SL_DATALOCATOR_BUFFERQUEUE:
533a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten    case SL_DATALOCATOR_MIDIBUFFERQUEUE:
534a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten        result = checkDataFormat(myDataSrc.pFormat, &pDataLocatorFormat->mFormat);
535a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten        if (SL_RESULT_SUCCESS != result) {
536a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten            freeDataLocator(&pDataLocatorFormat->mLocator);
537a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten            return result;
538a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten        }
539a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten        break;
540a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten    case SL_DATALOCATOR_NULL:
541a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten    case SL_DATALOCATOR_OUTPUTMIX:
542a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten    default:
543a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten        // invalid but fall through; the invalid locator will be caught later
5440b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten        SL_LOGE("mLocatorType=%u", (unsigned) pDataLocatorFormat->mLocator.mLocatorType);
5450b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten        // keep going
546a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten    case SL_DATALOCATOR_IODEVICE:
547a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten        // for these data locator types, ignore the pFormat as it might be uninitialized
548a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten        pDataLocatorFormat->mFormat.mFormatType = SL_DATAFORMAT_NULL;
549a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten        break;
550daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    }
551acd88797a1d3b8225bab888d29036e245f275be5Glenn Kasten    pDataLocatorFormat->u.mSource.pLocator = &pDataLocatorFormat->mLocator;
552acd88797a1d3b8225bab888d29036e245f275be5Glenn Kasten    pDataLocatorFormat->u.mSource.pFormat = &pDataLocatorFormat->mFormat;
553daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    return SL_RESULT_SUCCESS;
554daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten}
555daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten
5560b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
557e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten/** \brief Check a data sink and make local deep copy */
5580b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
559712b490060e4164fbe47986be1d2584d1610d8ddJean-Michel TriviSLresult checkDataSink(const SLDataSink *pDataSink, DataLocatorFormat *pDataLocatorFormat,
560712b490060e4164fbe47986be1d2584d1610d8ddJean-Michel Trivi        SLuint32 objType)
561daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten{
562daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    if (NULL == pDataSink)
563daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
564daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    SLDataSink myDataSink = *pDataSink;
565daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    SLresult result;
566daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    result = checkDataLocator(myDataSink.pLocator, &pDataLocatorFormat->mLocator);
567712b490060e4164fbe47986be1d2584d1610d8ddJean-Michel Trivi    if (SL_RESULT_SUCCESS != result) {
568daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        return result;
569712b490060e4164fbe47986be1d2584d1610d8ddJean-Michel Trivi    }
570a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten    switch (pDataLocatorFormat->mLocator.mLocatorType) {
571712b490060e4164fbe47986be1d2584d1610d8ddJean-Michel Trivi
572a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten    case SL_DATALOCATOR_URI:
573a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten    case SL_DATALOCATOR_ADDRESS:
574a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten        result = checkDataFormat(myDataSink.pFormat, &pDataLocatorFormat->mFormat);
575a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten        if (SL_RESULT_SUCCESS != result) {
576a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten            freeDataLocator(&pDataLocatorFormat->mLocator);
577a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten            return result;
578a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten        }
579a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten        break;
580712b490060e4164fbe47986be1d2584d1610d8ddJean-Michel Trivi
581a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten    case SL_DATALOCATOR_BUFFERQUEUE:
582712b490060e4164fbe47986be1d2584d1610d8ddJean-Michel Trivi        if (SL_OBJECTID_AUDIOPLAYER == objType) {
583712b490060e4164fbe47986be1d2584d1610d8ddJean-Michel Trivi            return SL_RESULT_PARAMETER_INVALID;
584712b490060e4164fbe47986be1d2584d1610d8ddJean-Michel Trivi        } else if (SL_OBJECTID_AUDIORECORDER == objType) {
585712b490060e4164fbe47986be1d2584d1610d8ddJean-Michel Trivi#ifdef ANDROID
586712b490060e4164fbe47986be1d2584d1610d8ddJean-Michel Trivi            result = checkDataFormat(myDataSink.pFormat, &pDataLocatorFormat->mFormat);
587712b490060e4164fbe47986be1d2584d1610d8ddJean-Michel Trivi            if (SL_RESULT_SUCCESS != result) {
588712b490060e4164fbe47986be1d2584d1610d8ddJean-Michel Trivi                return result;
589712b490060e4164fbe47986be1d2584d1610d8ddJean-Michel Trivi            }
590712b490060e4164fbe47986be1d2584d1610d8ddJean-Michel Trivi            break;
591712b490060e4164fbe47986be1d2584d1610d8ddJean-Michel Trivi#else
592712b490060e4164fbe47986be1d2584d1610d8ddJean-Michel Trivi            SL_LOGE("mLocatorType=%u", (unsigned) pDataLocatorFormat->mLocator.mLocatorType);
593712b490060e4164fbe47986be1d2584d1610d8ddJean-Michel Trivi            freeDataLocator(&pDataLocatorFormat->mLocator);
594712b490060e4164fbe47986be1d2584d1610d8ddJean-Michel Trivi            return SL_RESULT_PARAMETER_INVALID;
595712b490060e4164fbe47986be1d2584d1610d8ddJean-Michel Trivi#endif
596712b490060e4164fbe47986be1d2584d1610d8ddJean-Michel Trivi        }
597712b490060e4164fbe47986be1d2584d1610d8ddJean-Michel Trivi        break;
598712b490060e4164fbe47986be1d2584d1610d8ddJean-Michel Trivi
599712b490060e4164fbe47986be1d2584d1610d8ddJean-Michel Trivi    case SL_DATALOCATOR_NULL:
600a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten    case SL_DATALOCATOR_MIDIBUFFERQUEUE:
601a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten    default:
602a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten        // invalid but fall through; the invalid locator will be caught later
6030b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten        SL_LOGE("mLocatorType=%u", (unsigned) pDataLocatorFormat->mLocator.mLocatorType);
6040b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten        // keep going
605a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten    case SL_DATALOCATOR_IODEVICE:
606a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten    case SL_DATALOCATOR_OUTPUTMIX:
607a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten        // for these data locator types, ignore the pFormat as it might be uninitialized
608a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten        pDataLocatorFormat->mFormat.mFormatType = SL_DATAFORMAT_NULL;
609a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten        break;
610daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    }
611acd88797a1d3b8225bab888d29036e245f275be5Glenn Kasten    pDataLocatorFormat->u.mSink.pLocator = &pDataLocatorFormat->mLocator;
612acd88797a1d3b8225bab888d29036e245f275be5Glenn Kasten    pDataLocatorFormat->u.mSink.pFormat = &pDataLocatorFormat->mFormat;
613daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    return SL_RESULT_SUCCESS;
614daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten}
615daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten
6160b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
617e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten/** \brief Free the local deep copy of a data locator format */
6180b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
619daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kastenvoid freeDataLocatorFormat(DataLocatorFormat *dlf)
620daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten{
621daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    freeDataLocator(&dlf->mLocator);
622daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    freeDataFormat(&dlf->mFormat);
623daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten}
624daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten
6250b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
62661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten/* Interface initialization hooks */
6272045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
628a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kastenextern void
629a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    I3DCommit_init(void *),
630a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    I3DDoppler_init(void *),
631a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    I3DGrouping_init(void *),
632a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    I3DLocation_init(void *),
633a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    I3DMacroscopic_init(void *),
634a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    I3DSource_init(void *),
63561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IAudioDecoderCapabilities_init(void *),
63661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IAudioEncoderCapabilities_init(void *),
63761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IAudioEncoder_init(void *),
63861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IAudioIODeviceCapabilities_init(void *),
639a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IBassBoost_init(void *),
6400b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IBufferQueue_init(void *),
64161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IDeviceVolume_init(void *),
64261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IDynamicInterfaceManagement_init(void *),
64361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IDynamicSource_init(void *),
64461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IEffectSend_init(void *),
6450b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IEngineCapabilities_init(void *),
6460b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IEngine_init(void *),
647a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IEnvironmentalReverb_init(void *),
648a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IEqualizer_init(void *),
64961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    ILEDArray_init(void *),
6500b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IMIDIMessage_init(void *),
6510b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IMIDIMuteSolo_init(void *),
6520b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IMIDITempo_init(void *),
6530b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IMIDITime_init(void *),
65461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IMetadataExtraction_init(void *),
65561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IMetadataTraversal_init(void *),
65661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IMuteSolo_init(void *),
65761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IObject_init(void *),
6580b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IOutputMix_init(void *),
65961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IPitch_init(void *),
6600b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IPlay_init(void *),
66161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IPlaybackRate_init(void *),
66261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IPrefetchStatus_init(void *),
663a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IPresetReverb_init(void *),
66461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IRatePitch_init(void *),
66561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IRecord_init(void *),
6660b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    ISeek_init(void *),
66761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IThreadSync_init(void *),
66861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IVibra_init(void *),
669a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IVirtualizer_init(void *),
6700b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IVisualization_init(void *),
6710b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IVolume_init(void *);
67205ccff2aaa3e1507cdc7ab3b244c973c6708e009Jean-Michel Trivi#ifdef ANDROID
67367bdf8a2fbd1024ab50c4513e1504325475368e0Jean-Michel Triviextern void IAndroidStreamType_init(void *);
67467bdf8a2fbd1024ab50c4513e1504325475368e0Jean-Michel Triviextern void IAndroidAudioEffect_init(void *);
67505ccff2aaa3e1507cdc7ab3b244c973c6708e009Jean-Michel Trivi#endif
676a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten
677b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten#ifdef USE_OUTPUTMIXEXT
678b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kastenextern void
679b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    IOutputMixExt_init(void *);
680b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten#endif
6814597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kastenextern void
6824597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten    IObject_deinit(void *);
683b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten
684e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten
68561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten/*static*/ const struct MPH_init MPH_init_table[MPH_MAX] = {
686510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_3DCOMMIT, */ I3DCommit_init, NULL, NULL },
687510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_3DDOPPLER, */ I3DDoppler_init, NULL, NULL },
688510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_3DGROUPING, */ I3DGrouping_init, NULL, NULL },
689510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_3DLOCATION, */ I3DLocation_init, NULL, NULL },
690510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_3DMACROSCOPIC, */ I3DMacroscopic_init, NULL, NULL },
691510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_3DSOURCE, */ I3DSource_init, NULL, NULL },
692510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_AUDIODECODERCAPABILITIES, */ IAudioDecoderCapabilities_init, NULL, NULL },
693510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_AUDIOENCODER, */ IAudioEncoder_init, NULL, NULL },
694510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_AUDIOENCODERCAPABILITIES, */ IAudioEncoderCapabilities_init, NULL, NULL },
695510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_AUDIOIODEVICECAPABILITIES, */ IAudioIODeviceCapabilities_init, NULL, NULL },
696510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_BASSBOOST, */ IBassBoost_init, NULL, NULL },
697510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_BUFFERQUEUE, */ IBufferQueue_init, NULL, NULL },
698510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_DEVICEVOLUME, */ IDeviceVolume_init, NULL, NULL },
699510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_DYNAMICINTERFACEMANAGEMENT, */ IDynamicInterfaceManagement_init, NULL, NULL },
700510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_DYNAMICSOURCE, */ IDynamicSource_init, NULL, NULL },
701510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_EFFECTSEND, */ IEffectSend_init, NULL, NULL },
702510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_ENGINE, */ IEngine_init, NULL, NULL },
703510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_ENGINECAPABILITIES, */ IEngineCapabilities_init, NULL, NULL },
704510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_ENVIRONMENTALREVERB, */ IEnvironmentalReverb_init, NULL, NULL },
705510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_EQUALIZER, */ IEqualizer_init, NULL, NULL },
706510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_LED, */ ILEDArray_init, NULL, NULL },
707510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_METADATAEXTRACTION, */ IMetadataExtraction_init, NULL, NULL },
708510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_METADATATRAVERSAL, */ IMetadataTraversal_init, NULL, NULL },
709510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_MIDIMESSAGE, */ IMIDIMessage_init, NULL, NULL },
710510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_MIDITIME, */ IMIDITime_init, NULL, NULL },
711510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_MIDITEMPO, */ IMIDITempo_init, NULL, NULL },
712510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_MIDIMUTESOLO, */ IMIDIMuteSolo_init, NULL, NULL },
713510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_MUTESOLO, */ IMuteSolo_init, NULL, NULL },
714510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_NULL, */ NULL, NULL, NULL },
7154597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten    { /* MPH_OBJECT, */ IObject_init, NULL, IObject_deinit },
716510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_OUTPUTMIX, */ IOutputMix_init, NULL, NULL },
717510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_PITCH, */ IPitch_init, NULL, NULL },
718510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_PLAY, */ IPlay_init, NULL, NULL },
719510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_PLAYBACKRATE, */ IPlaybackRate_init, NULL, NULL },
720510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_PREFETCHSTATUS, */ IPrefetchStatus_init, NULL, NULL },
721510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_PRESETREVERB, */ IPresetReverb_init, NULL, NULL },
722510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_RATEPITCH, */ IRatePitch_init, NULL, NULL },
723510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_RECORD, */ IRecord_init, NULL, NULL },
724510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_SEEK, */ ISeek_init, NULL, NULL },
725510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_THREADSYNC, */ IThreadSync_init, NULL, NULL },
726510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_VIBRA, */ IVibra_init, NULL, NULL },
727510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_VIRTUALIZER, */ IVirtualizer_init, NULL, NULL },
728510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_VISUALIZATION, */ IVisualization_init, NULL, NULL },
729510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_VOLUME, */ IVolume_init, NULL, NULL },
730bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#ifdef USE_OUTPUTMIXEXT
731a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten    { /* MPH_OUTPUTMIXEXT, */ IOutputMixExt_init, NULL, NULL },
732bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#else
733a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten    { /* MPH_OUTPUTMIXEXT, */ NULL, NULL, NULL },
734bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#endif
73505ccff2aaa3e1507cdc7ab3b244c973c6708e009Jean-Michel Trivi#ifdef ANDROID
73667bdf8a2fbd1024ab50c4513e1504325475368e0Jean-Michel Trivi    { /* MPH_ANDROIDSTREAMTYPE */ IAndroidStreamType_init, NULL, NULL },
73767bdf8a2fbd1024ab50c4513e1504325475368e0Jean-Michel Trivi    { /* MPH_ANDROIDAUDIOEFFECT */ IAndroidAudioEffect_init, NULL, NULL }
738a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten#else
73967bdf8a2fbd1024ab50c4513e1504325475368e0Jean-Michel Trivi    { /* MPH_ANDROIDSTREAMTYPE */ NULL, NULL, NULL },
74067bdf8a2fbd1024ab50c4513e1504325475368e0Jean-Michel Trivi    { /* MPH_ANDROIDAUDIOEFFECT */ NULL, NULL, NULL }
74105ccff2aaa3e1507cdc7ab3b244c973c6708e009Jean-Michel Trivi#endif
742bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten};
743bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
7440b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
745e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten/** \brief Construct a new instance of the specified class, exposing selected interfaces */
746bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
747ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn KastenIObject *construct(const ClassTable *class__, unsigned exposedMask, SLEngineItf engine)
748bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
74972a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IObject *this;
75072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    this = (IObject *) calloc(1, class__->mSize);
751bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    if (NULL != this) {
75272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        unsigned lossOfControlMask = 0;
753ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten        // a NULL engine means we are constructing the engine
75472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        IEngine *thisEngine = (IEngine *) engine;
755d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten        if (NULL == thisEngine) {
75672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten            thisEngine = &((CEngine *) this)->mEngine;
757d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten        } else {
758ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten            interface_lock_exclusive(thisEngine);
759d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten            if (MAX_INSTANCE <= thisEngine->mInstanceCount) {
760ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten                // too many objects
761ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten                interface_unlock_exclusive(thisEngine);
762d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten                free(this);
763ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten                return NULL;
764ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten            }
765d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten            // pre-allocate a pending slot, but don't assign bit from mInstanceMask yet
766ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten            ++thisEngine->mInstanceCount;
767d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten            assert(((unsigned) ~0) != thisEngine->mInstanceMask);
768ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten            interface_unlock_exclusive(thisEngine);
769ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten            // const, no lock needed
770ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten            if (thisEngine->mLossOfControlGlobal)
771ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten                lossOfControlMask = ~0;
772ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten        }
77372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        this->mLossOfControlMask = lossOfControlMask;
774ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten        this->mClass = class__;
775ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten        this->mEngine = thisEngine;
776bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        const struct iid_vtable *x = class__->mInterfaces;
777510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        SLuint8 *interfaceStateP = this->mInterfaceStates;
778510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        SLuint32 index;
779510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        for (index = 0; index < class__->mInterfaceCount; ++index, ++x, exposedMask >>= 1) {
780276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten            SLuint8 state;
781bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten            if (exposedMask & 1) {
78283f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten                void *self = (char *) this + x->mOffset;
783d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten                // IObject does not have an mThis, so [1] is not always defined
784d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten                if (index)
785d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten                    ((IObject **) self)[1] = this;
78683f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten                VoidHook init = MPH_init_table[x->mMPH].mInit;
787bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten                if (NULL != init)
788bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten                    (*init)(self);
789e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten                // IObject does not require a call to GetInterface
790e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten                if (index)
791e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten                    ((size_t *) self)[0] ^= ~0;
792510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten                state = INTERFACE_EXPOSED;
793510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            } else
794510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten                state = INTERFACE_UNINITIALIZED;
795510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            *interfaceStateP++ = state;
796bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        }
797ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten        // only expose new object to sync thread after it is fully initialized
798ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten        interface_lock_exclusive(thisEngine);
799d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten        unsigned availMask = ~thisEngine->mInstanceMask;
800d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten        assert(availMask);
801d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten        unsigned i = ctz(availMask);
802d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten        assert(MAX_INSTANCE > i);
803d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten        assert(NULL == thisEngine->mInstances[i]);
804d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten        thisEngine->mInstances[i] = this;
805d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten        thisEngine->mInstanceMask |= 1 << i;
806d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten        // avoid zero as a valid instance ID
807d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten        this->mInstanceID = i + 1;
80800d2d554e04ac369367c903dbf53b975355d1bcdGlenn Kasten#ifdef USE_SDL
80900d2d554e04ac369367c903dbf53b975355d1bcdGlenn Kasten        SLboolean unpause = SL_BOOLEAN_FALSE;
81000d2d554e04ac369367c903dbf53b975355d1bcdGlenn Kasten        if (SL_OBJECTID_OUTPUTMIX == class__->mObjectID && NULL == thisEngine->mOutputMix) {
81100d2d554e04ac369367c903dbf53b975355d1bcdGlenn Kasten            thisEngine->mOutputMix = (COutputMix *) this;
81200d2d554e04ac369367c903dbf53b975355d1bcdGlenn Kasten            unpause = SL_BOOLEAN_TRUE;
81300d2d554e04ac369367c903dbf53b975355d1bcdGlenn Kasten        }
81400d2d554e04ac369367c903dbf53b975355d1bcdGlenn Kasten#endif
815ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten        interface_unlock_exclusive(thisEngine);
81600d2d554e04ac369367c903dbf53b975355d1bcdGlenn Kasten#ifdef USE_SDL
81700d2d554e04ac369367c903dbf53b975355d1bcdGlenn Kasten        if (unpause)
81800d2d554e04ac369367c903dbf53b975355d1bcdGlenn Kasten            SDL_PauseAudio(0);
81900d2d554e04ac369367c903dbf53b975355d1bcdGlenn Kasten#endif
820bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    }
821bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return this;
822bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
823bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
824ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
825ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten/* Initial global entry points */
826d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
8270b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
828e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten/** \brief slCreateEngine Function */
8290b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
8300b167267bda99b68346045ccab14e810121d5de4Glenn KastenSLresult SLAPIENTRY slCreateEngine(SLObjectItf *pEngine, SLuint32 numOptions,
8310b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    const SLEngineOption *pEngineOptions, SLuint32 numInterfaces,
8320b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired)
833d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
834ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_ENTER_GLOBAL
835ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
836ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    do {
837ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
838ef8931ae547cd703e69df9ad350d69825da0f546Jean-Michel Trivi#ifdef ANDROID
839ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        android::ProcessState::self()->startThreadPool();
84014e903028c4abfc1b2fbfab6560e3b864086f895Glenn Kasten#ifndef USE_BACKPORT
841ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        android::DataSource::RegisterDefaultSniffers();
8426fff2c605cdc46a10037e011d8fb47702ae70c37Jean-Michel Trivi#endif
84314e903028c4abfc1b2fbfab6560e3b864086f895Glenn Kasten#endif
844ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
845ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        if (NULL == pEngine) {
846ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            result = SL_RESULT_PARAMETER_INVALID;
847ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            break;
848ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        }
849ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        *pEngine = NULL;
850ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
851ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        if ((0 < numOptions) && (NULL == pEngineOptions)) {
852ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            result = SL_RESULT_PARAMETER_INVALID;
853ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            break;
854ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        }
855ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
856ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        // default values
857ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        SLboolean threadSafe = SL_BOOLEAN_TRUE;
858ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        SLboolean lossOfControlGlobal = SL_BOOLEAN_FALSE;
859ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
860ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        // process engine options
8610b167267bda99b68346045ccab14e810121d5de4Glenn Kasten        SLuint32 i;
8620b167267bda99b68346045ccab14e810121d5de4Glenn Kasten        const SLEngineOption *option = pEngineOptions;
863ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        result = SL_RESULT_SUCCESS;
8640b167267bda99b68346045ccab14e810121d5de4Glenn Kasten        for (i = 0; i < numOptions; ++i, ++option) {
8650b167267bda99b68346045ccab14e810121d5de4Glenn Kasten            switch (option->feature) {
8660b167267bda99b68346045ccab14e810121d5de4Glenn Kasten            case SL_ENGINEOPTION_THREADSAFE:
8674b2f97bb1df6b3a65d2c3a158fba3a604c8f543cGlenn Kasten                threadSafe = SL_BOOLEAN_FALSE != (SLboolean) option->data; // normalize
8680b167267bda99b68346045ccab14e810121d5de4Glenn Kasten                break;
8690b167267bda99b68346045ccab14e810121d5de4Glenn Kasten            case SL_ENGINEOPTION_LOSSOFCONTROL:
8704b2f97bb1df6b3a65d2c3a158fba3a604c8f543cGlenn Kasten                lossOfControlGlobal = SL_BOOLEAN_FALSE != (SLboolean) option->data; // normalize
8710b167267bda99b68346045ccab14e810121d5de4Glenn Kasten                break;
8720b167267bda99b68346045ccab14e810121d5de4Glenn Kasten            default:
873ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                result = SL_RESULT_PARAMETER_INVALID;
874ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                break;
8750b167267bda99b68346045ccab14e810121d5de4Glenn Kasten            }
8760b167267bda99b68346045ccab14e810121d5de4Glenn Kasten        }
877ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        if (SL_RESULT_SUCCESS != result)
878ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            break;
879ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
880ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        unsigned exposedMask;
881ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        const ClassTable *pCEngine_class = objectIDtoClass(SL_OBJECTID_ENGINE);
882ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        result = checkInterfaces(pCEngine_class, numInterfaces,
883ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            pInterfaceIds, pInterfaceRequired, &exposedMask);
884ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        if (SL_RESULT_SUCCESS != result)
885ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            break;
886ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
887ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        CEngine *this = (CEngine *) construct(pCEngine_class, exposedMask, NULL);
888ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        if (NULL == this) {
889ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            result = SL_RESULT_MEMORY_FAILURE;
890ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            break;
891ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        }
892ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
893ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        this->mObject.mLossOfControlMask = lossOfControlGlobal ? ~0 : 0;
894ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        this->mEngine.mLossOfControlGlobal = lossOfControlGlobal;
895ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        this->mEngineCapabilities.mThreadSafe = threadSafe;
896ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        *pEngine = &this->mObject.mItf;
897ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
898ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    } while(0);
899ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
900ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_LEAVE_GLOBAL
901d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
902d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
903ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
904e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten/** \brief slQueryNumSupportedEngineInterfaces Function */
9050b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
906ed46c29d6a09112dbbf584c82953f63289596fd6Glenn KastenSLresult SLAPIENTRY slQueryNumSupportedEngineInterfaces(SLuint32 *pNumSupportedInterfaces)
907d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
908ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_ENTER_GLOBAL
909ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
910ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    if (NULL == pNumSupportedInterfaces) {
911ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
912ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    } else {
9137a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten        const ClassTable *class__ = objectIDtoClass(SL_OBJECTID_ENGINE);
9147a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten        assert(NULL != class__);
9157a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten        SLuint32 count = 0;
9167a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten        SLuint32 i;
917c3845706778edec308bd9ced559cec0a456608bdGlenn Kasten        for (i = 0; i < class__->mInterfaceCount; ++i) {
918c3845706778edec308bd9ced559cec0a456608bdGlenn Kasten            switch (class__->mInterfaces[i].mInterface) {
919c3845706778edec308bd9ced559cec0a456608bdGlenn Kasten            case INTERFACE_IMPLICIT:
920c3845706778edec308bd9ced559cec0a456608bdGlenn Kasten            case INTERFACE_EXPLICIT:
921c3845706778edec308bd9ced559cec0a456608bdGlenn Kasten            case INTERFACE_DYNAMIC:
9227a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten                ++count;
923c3845706778edec308bd9ced559cec0a456608bdGlenn Kasten                break;
924c3845706778edec308bd9ced559cec0a456608bdGlenn Kasten            case INTERFACE_UNAVAILABLE:
925c3845706778edec308bd9ced559cec0a456608bdGlenn Kasten                break;
926c3845706778edec308bd9ced559cec0a456608bdGlenn Kasten            default:
927c3845706778edec308bd9ced559cec0a456608bdGlenn Kasten                assert(false);
928c3845706778edec308bd9ced559cec0a456608bdGlenn Kasten                break;
929c3845706778edec308bd9ced559cec0a456608bdGlenn Kasten            }
930c3845706778edec308bd9ced559cec0a456608bdGlenn Kasten        }
9317a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten        *pNumSupportedInterfaces = count;
932ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        result = SL_RESULT_SUCCESS;
933ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    }
934ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
935ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_LEAVE_GLOBAL
936d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
937d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
938ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
939e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten/** \brief slQuerySupportedEngineInterfaces Function */
9400b595cc18d82e41dfab0c686e9e63c30a86e8c80Glenn Kasten
941ed46c29d6a09112dbbf584c82953f63289596fd6Glenn KastenSLresult SLAPIENTRY slQuerySupportedEngineInterfaces(SLuint32 index, SLInterfaceID *pInterfaceId)
942d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
943ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_ENTER_GLOBAL
944ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
945ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    if (NULL == pInterfaceId) {
946ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
947ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    } else {
9487a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten        *pInterfaceId = NULL;
9497a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten        const ClassTable *class__ = objectIDtoClass(SL_OBJECTID_ENGINE);
9507a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten        assert(NULL != class__);
9517a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten        result = SL_RESULT_PARAMETER_INVALID;   // will be reset later
9527a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten        SLuint32 i;
9537a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten        for (i = 0; i < class__->mInterfaceCount; ++i) {
954c3845706778edec308bd9ced559cec0a456608bdGlenn Kasten            switch (class__->mInterfaces[i].mInterface) {
955c3845706778edec308bd9ced559cec0a456608bdGlenn Kasten            case INTERFACE_IMPLICIT:
956c3845706778edec308bd9ced559cec0a456608bdGlenn Kasten            case INTERFACE_EXPLICIT:
957c3845706778edec308bd9ced559cec0a456608bdGlenn Kasten            case INTERFACE_DYNAMIC:
958c3845706778edec308bd9ced559cec0a456608bdGlenn Kasten                break;
959c3845706778edec308bd9ced559cec0a456608bdGlenn Kasten            case INTERFACE_UNAVAILABLE:
9607a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten                continue;
961c3845706778edec308bd9ced559cec0a456608bdGlenn Kasten            default:
962c3845706778edec308bd9ced559cec0a456608bdGlenn Kasten                assert(false);
963c3845706778edec308bd9ced559cec0a456608bdGlenn Kasten                break;
964c3845706778edec308bd9ced559cec0a456608bdGlenn Kasten            }
9657a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten            if (index == 0) {
9667a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten                *pInterfaceId = &SL_IID_array[class__->mInterfaces[i].mMPH];
9677a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten                result = SL_RESULT_SUCCESS;
9687a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten                break;
9697a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten            }
9707a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten            --index;
971ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        }
972ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    }
973ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
974ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_LEAVE_GLOBAL
975d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
976d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
977ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
978d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten/* End */
979