sles.cpp revision d07ed7df4ec9338f97f12627690d58ed9b34f25b
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
17d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten/* OpenSL ES prototype */
18d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
19773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi#include "sles_allinclusive.h"
20d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
21bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/* Private functions */
22bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
23b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten// Map an IObject to it's "object ID" (which is really a class ID)
24b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten
25b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn KastenSLuint32 IObjectToObjectID(IObject *this)
26b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten{
27b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    assert(NULL != this);
28b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    return this->mClass->mObjectID;
29b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten}
30b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten
31bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten// Map SLInterfaceID to its minimal perfect hash (MPH), or -1 if unknown
32bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
3361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten/*static*/ int IID_to_MPH(const SLInterfaceID iid)
34d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
35bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    if (&SL_IID_array[0] <= iid && &SL_IID_array[MPH_MAX] > iid)
36bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        return iid - &SL_IID_array[0];
37bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    if (NULL != iid) {
38bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        // FIXME Replace this linear search by a good MPH algorithm
39bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        const struct SLInterfaceID_ *srch = &SL_IID_array[0];
40bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        unsigned MPH;
41bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        for (MPH = 0; MPH < MPH_MAX; ++MPH, ++srch)
42bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten            if (!memcmp(iid, srch, sizeof(struct SLInterfaceID_)))
43bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten                return MPH;
44bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    }
45bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return -1;
46bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
47bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
48d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten// Convert POSIX pthread error code to OpenSL ES result code
49d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten
50d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn KastenSLresult err_to_result(int err)
51d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten{
52d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten    if (EAGAIN == err || ENOMEM == err)
53d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten        return SL_RESULT_RESOURCE_ERROR;
54d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten    if (0 != err)
55d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten        return SL_RESULT_INTERNAL_ERROR;
56d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten    return SL_RESULT_SUCCESS;
57d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten}
58d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten
5929b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten// Check the interface IDs passed into a Create operation
6029b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten
61979a3f8743646af9999a89dff9e13b972b7efd87Glenn KastenSLresult checkInterfaces(const ClassTable *class__,
62bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLuint32 numInterfaces, const SLInterfaceID *pInterfaceIds,
63bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    const SLboolean *pInterfaceRequired, unsigned *pExposedMask)
64bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
65bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    assert(NULL != class__ && NULL != pExposedMask);
66bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    unsigned exposedMask = 0;
67bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    const struct iid_vtable *interfaces = class__->mInterfaces;
68bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLuint32 interfaceCount = class__->mInterfaceCount;
69bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    SLuint32 i;
70bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    // FIXME This section could be pre-computed per class
71bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    for (i = 0; i < interfaceCount; ++i) {
72bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        switch (interfaces[i].mInterface) {
73bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        case INTERFACE_IMPLICIT:
74bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten            exposedMask |= 1 << i;
75bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten            break;
76bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        default:
77bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten            break;
78bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        }
79bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    }
80d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    if (0 < numInterfaces) {
81d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten        if (NULL == pInterfaceIds || NULL == pInterfaceRequired)
82d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten            return SL_RESULT_PARAMETER_INVALID;
83d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten        for (i = 0; i < numInterfaces; ++i) {
84bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten            SLInterfaceID iid = pInterfaceIds[i];
85bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten            if (NULL == iid)
86bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten                return SL_RESULT_PARAMETER_INVALID;
8729b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            int MPH, index;
8829b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            if ((0 > (MPH = IID_to_MPH(iid))) ||
8929b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten                (0 > (index = class__->mMPH_to_index[MPH]))) {
90bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten                if (pInterfaceRequired[i])
91bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten                    return SL_RESULT_FEATURE_UNSUPPORTED;
92bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten                continue;
93bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten            }
9429b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            // FIXME this seems a bit strong? what is correct logic?
9529b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            // we are requesting a duplicate explicit interface,
9629b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            // or we are requesting one which is already implicit ?
9729b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            // if (exposedMask & (1 << index))
9829b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            //    return SL_RESULT_PARAMETER_INVALID;
99daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            // can we request dynamic interfaces here?
10029b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten            exposedMask |= (1 << index);
101d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten        }
102d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    }
103bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    *pExposedMask = exposedMask;
104d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    return SL_RESULT_SUCCESS;
105d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
106d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
10761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten// private helper shared by decoder and encoder
10861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn KastenSLresult GetCodecCapabilities(SLuint32 decoderId, SLuint32 *pIndex,
10961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    SLAudioCodecDescriptor *pDescriptor,
11061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    const struct CodecDescriptor *codecDescriptors)
111bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
11261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    if (NULL == pIndex)
11361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
11461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    const struct CodecDescriptor *cd = codecDescriptors;
11561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    SLuint32 index;
11661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    if (NULL == pDescriptor) {
11761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        for (index = 0 ; NULL != cd->mDescriptor; ++cd)
11861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten            if (cd->mCodecID == decoderId)
11961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten                ++index;
12061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        *pIndex = index;
12161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        return SL_RESULT_SUCCESS;
12261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    }
12361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    index = *pIndex;
12461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    for ( ; NULL != cd->mDescriptor; ++cd) {
12561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        if (cd->mCodecID == decoderId) {
12661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten            if (0 == index) {
12761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten                *pDescriptor = *cd->mDescriptor;
12861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten                return SL_RESULT_SUCCESS;
12961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten            }
13061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten            --index;
13161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        }
13261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    }
13361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    return SL_RESULT_PARAMETER_INVALID;
134bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
1352045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
136daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kastenstatic SLresult checkDataLocator(void *pLocator, DataLocator *pDataLocator)
137daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten{
138daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    if (NULL == pLocator) {
139daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        pDataLocator->mLocatorType = 0;
140daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        return SL_RESULT_SUCCESS;
141daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    }
142daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    SLuint32 locatorType = *(SLuint32 *)pLocator;
143daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    switch (locatorType) {
144daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    case SL_DATALOCATOR_ADDRESS:
145daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        pDataLocator->mAddress = *(SLDataLocator_Address *)pLocator;
146daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        if (0 < pDataLocator->mAddress.length && NULL == pDataLocator->mAddress.pAddress)
147daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            return SL_RESULT_PARAMETER_INVALID;
148daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        break;
149daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    case SL_DATALOCATOR_BUFFERQUEUE:
150daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        pDataLocator->mBufferQueue = *(SLDataLocator_BufferQueue *)pLocator;
151daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        if (0 == pDataLocator->mBufferQueue.numBuffers)
152daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            return SL_RESULT_PARAMETER_INVALID;
153daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            // pDataLocator->mBufferQueue.numBuffers = 2;
154daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        // FIXME check against a max
155daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        break;
156daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    case SL_DATALOCATOR_IODEVICE:
157daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        {
158daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        pDataLocator->mIODevice = *(SLDataLocator_IODevice *)pLocator;
159daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        SLuint32 deviceType = pDataLocator->mIODevice.deviceType;
160daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        if (NULL != pDataLocator->mIODevice.device) {
161daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            switch (IObjectToObjectID((IObject *) pDataLocator->mIODevice.device)) {
162daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            case SL_OBJECTID_LEDDEVICE:
163daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten                if (SL_IODEVICE_LEDARRAY != deviceType)
164daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten                    return SL_RESULT_PARAMETER_INVALID;
165daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten                break;
166daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            case SL_OBJECTID_VIBRADEVICE:
167daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten                if (SL_IODEVICE_VIBRA != deviceType)
168daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten                    return SL_RESULT_PARAMETER_INVALID;
169daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten                break;
170daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            default:
171daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten                return SL_RESULT_PARAMETER_INVALID;
172daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            }
173daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            pDataLocator->mIODevice.deviceID = 0;
174daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        } else {
175daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            switch (pDataLocator->mIODevice.deviceID) {
176daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            case SL_DEFAULTDEVICEID_LED:
177daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten                if (SL_IODEVICE_LEDARRAY != deviceType)
178daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten                    return SL_RESULT_PARAMETER_INVALID;
179daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten                break;
180daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            case SL_DEFAULTDEVICEID_VIBRA:
181daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten                if (SL_IODEVICE_VIBRA != deviceType)
182daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten                    return SL_RESULT_PARAMETER_INVALID;
183daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten                break;
184daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            case SL_DEFAULTDEVICEID_AUDIOINPUT:
185daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten                if (SL_IODEVICE_AUDIOINPUT != deviceType)
186daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten                    return SL_RESULT_PARAMETER_INVALID;
187daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten                break;
188daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            default:
189daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten                return SL_RESULT_PARAMETER_INVALID;
190daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            }
191daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        }
192daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        }
193daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        break;
194daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    case SL_DATALOCATOR_MIDIBUFFERQUEUE:
195daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        pDataLocator->mMIDIBufferQueue = *(SLDataLocator_MIDIBufferQueue *)pLocator;
196daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        if (0 == pDataLocator->mMIDIBufferQueue.tpqn)
197daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            pDataLocator->mMIDIBufferQueue.tpqn = 192;
198daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        if (0 == pDataLocator->mMIDIBufferQueue.numBuffers)
199daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            pDataLocator->mMIDIBufferQueue.numBuffers = 2;
200daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        break;
201daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    case SL_DATALOCATOR_OUTPUTMIX:
202daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        pDataLocator->mOutputMix = *(SLDataLocator_OutputMix *)pLocator;
203daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        if ((NULL == pDataLocator->mOutputMix.outputMix) || (SL_OBJECTID_OUTPUTMIX != IObjectToObjectID((IObject *) pDataLocator->mOutputMix.outputMix)))
204daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            return SL_RESULT_PARAMETER_INVALID;
205daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        break;
206daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    case SL_DATALOCATOR_URI:
207daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        {
208daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        pDataLocator->mURI = *(SLDataLocator_URI *)pLocator;
209daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        if (NULL == pDataLocator->mURI.URI)
210daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            return SL_RESULT_PARAMETER_INVALID;
211daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        size_t len = strlen((const char *) pDataLocator->mURI.URI);
212daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        SLchar *myURI = (SLchar *) malloc(len + 1);
213daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        if (NULL == myURI)
214daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            return SL_RESULT_MEMORY_FAILURE;
215daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        memcpy(myURI, pDataLocator->mURI.URI, len + 1);
216daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        // Verify that another thread didn't change the NUL-terminator after we used it
217daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        // to determine length of string to copy. It's OK if the string became shorter.
218daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        if ('\0' != myURI[len]) {
219daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            free(myURI);
220daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            return SL_RESULT_PARAMETER_INVALID;
221daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        }
222daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        pDataLocator->mURI.URI = myURI;
223daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        }
224daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        break;
225daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    default:
226daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
227daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    }
228daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    // Verify that another thread didn't change the locatorType field after we used it
229daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    // to determine sizeof struct to copy.
230daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    if (locatorType != pDataLocator->mLocatorType)
231daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
232daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    return SL_RESULT_SUCCESS;
233daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten}
234daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten
235daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kastenstatic void freeDataLocator(DataLocator *pDataLocator)
236daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten{
237daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    switch (pDataLocator->mLocatorType) {
238daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    case SL_DATALOCATOR_URI:
239daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        free(pDataLocator->mURI.URI);
24000d2d554e04ac369367c903dbf53b975355d1bcdGlenn Kasten        pDataLocator->mURI.URI = NULL;
241daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        break;
242daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    default:
243daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        break;
244daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    }
245daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten}
246daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten
247daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kastenstatic SLresult checkDataFormat(void *pFormat, DataFormat *pDataFormat)
248daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten{
249daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    if (NULL == pFormat) {
250daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        pDataFormat->mFormatType = 0;
251daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        return SL_RESULT_SUCCESS;
252daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    }
253daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    SLuint32 formatType = *(SLuint32 *)pFormat;
254daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    switch (formatType) {
255daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    case SL_DATAFORMAT_PCM:
256daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        pDataFormat->mPCM = *(SLDataFormat_PCM *)pFormat;
257daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        switch (pDataFormat->mPCM.numChannels) {
258daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        case 1:
259daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        case 2:
260daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            break;
261daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        case 0:
262daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            return SL_RESULT_PARAMETER_INVALID;
263daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        default:
264daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            return SL_RESULT_CONTENT_UNSUPPORTED;
265daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        }
266daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        switch (pDataFormat->mPCM.samplesPerSec) {
267daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        case SL_SAMPLINGRATE_8:
268daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        case SL_SAMPLINGRATE_11_025:
269daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        case SL_SAMPLINGRATE_12:
270daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        case SL_SAMPLINGRATE_16:
271daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        case SL_SAMPLINGRATE_22_05:
272daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        case SL_SAMPLINGRATE_24:
273daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        case SL_SAMPLINGRATE_32:
274daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        case SL_SAMPLINGRATE_44_1:
275daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        case SL_SAMPLINGRATE_48:
276daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        case SL_SAMPLINGRATE_64:
277daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        case SL_SAMPLINGRATE_88_2:
278daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        case SL_SAMPLINGRATE_96:
279daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        case SL_SAMPLINGRATE_192:
280daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            break;
281daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        case 0:
282daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            return SL_RESULT_PARAMETER_INVALID;
283daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        default:
284daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            return SL_RESULT_CONTENT_UNSUPPORTED;
285daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        }
286daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        switch (pDataFormat->mPCM.bitsPerSample) {
287daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        case SL_PCMSAMPLEFORMAT_FIXED_8:
288daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        case SL_PCMSAMPLEFORMAT_FIXED_16:
289daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            break;
290daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        case SL_PCMSAMPLEFORMAT_FIXED_20:
291daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        case SL_PCMSAMPLEFORMAT_FIXED_24:
292daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        case SL_PCMSAMPLEFORMAT_FIXED_28:
293daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        case SL_PCMSAMPLEFORMAT_FIXED_32:
294daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            return SL_RESULT_CONTENT_UNSUPPORTED;
295daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        default:
296daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            return SL_RESULT_PARAMETER_INVALID;
297daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        }
298daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        switch (pDataFormat->mPCM.containerSize) {
299daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        case SL_PCMSAMPLEFORMAT_FIXED_8:
300daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        case SL_PCMSAMPLEFORMAT_FIXED_16:
301daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            if (pDataFormat->mPCM.containerSize != pDataFormat->mPCM.bitsPerSample)
302daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten                return SL_RESULT_CONTENT_UNSUPPORTED;
303daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            break;
304daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        default:
305daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            return SL_RESULT_CONTENT_UNSUPPORTED;
306daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        }
307daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        switch (pDataFormat->mPCM.channelMask) {
308daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        case SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT:
309daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            if (2 != pDataFormat->mPCM.numChannels)
310daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten                return SL_RESULT_PARAMETER_INVALID;
311daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            break;
312daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        case SL_SPEAKER_FRONT_LEFT:
313daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        case SL_SPEAKER_FRONT_RIGHT:
314daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        case SL_SPEAKER_FRONT_CENTER:
315daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            if (1 != pDataFormat->mPCM.numChannels)
316daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten                return SL_RESULT_PARAMETER_INVALID;
317daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            break;
318daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        case 0:
319daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            pDataFormat->mPCM.channelMask = pDataFormat->mPCM.numChannels == 2 ?  SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT : SL_SPEAKER_FRONT_CENTER;
320daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            break;
321daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        default:
322daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            return SL_RESULT_PARAMETER_INVALID;
323daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        }
324daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        switch (pDataFormat->mPCM.endianness) {
325daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        case SL_BYTEORDER_LITTLEENDIAN:
326daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            break;
327daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        case SL_BYTEORDER_BIGENDIAN:
328daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            return SL_RESULT_CONTENT_UNSUPPORTED;
329daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        default:
330daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            return SL_RESULT_PARAMETER_INVALID;
331daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        }
332daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        break;
333daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    case SL_DATAFORMAT_MIME:
334daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        {
335daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        pDataFormat->mMIME = *(SLDataFormat_MIME *)pFormat;
336daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        if (NULL == pDataFormat->mMIME.mimeType)
337daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            return SL_RESULT_SUCCESS;
338daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        size_t len = strlen((const char *) pDataFormat->mMIME.mimeType);
339daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        SLchar *myMIME = (SLchar *) malloc(len + 1);
340daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        if (NULL == myMIME)
341daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            return SL_RESULT_MEMORY_FAILURE;
342daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        memcpy(myMIME, pDataFormat->mMIME.mimeType, len + 1);
343daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        // ditto
344daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        if ('\0' != myMIME[len]) {
345daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            free(myMIME);
346daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            return SL_RESULT_PARAMETER_INVALID;
347daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        }
348daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        pDataFormat->mMIME.mimeType = myMIME;
349daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        }
350daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        break;
351daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    default:
352daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
353daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    }
354daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    if (formatType != pDataFormat->mFormatType)
355daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
356daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    return SL_RESULT_SUCCESS;
357daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten}
358daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten
359daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kastenstatic void freeDataFormat(DataFormat *pDataFormat)
360daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten{
361daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    switch (pDataFormat->mFormatType) {
362daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    case SL_DATAFORMAT_MIME:
363daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        free(pDataFormat->mMIME.mimeType);
36400d2d554e04ac369367c903dbf53b975355d1bcdGlenn Kasten        pDataFormat->mMIME.mimeType = NULL;
365daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        break;
366daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    default:
367daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        break;
368daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    }
369daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten}
370daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten
371daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn KastenSLresult checkDataSource(const SLDataSource *pDataSrc, DataLocatorFormat *pDataLocatorFormat)
372daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten{
373daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    if (NULL == pDataSrc)
374daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
375daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    SLDataSource myDataSrc = *pDataSrc;
376daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    SLresult result;
377daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    result = checkDataLocator(myDataSrc.pLocator, &pDataLocatorFormat->mLocator);
378daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    if (SL_RESULT_SUCCESS != result)
379daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        return result;
380daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    result = checkDataFormat(myDataSrc.pFormat, &pDataLocatorFormat->mFormat);
381daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    if (SL_RESULT_SUCCESS != result) {
382daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        freeDataLocator(&pDataLocatorFormat->mLocator);
383daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        return result;
384daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    }
385acd88797a1d3b8225bab888d29036e245f275be5Glenn Kasten    pDataLocatorFormat->u.mSource.pLocator = &pDataLocatorFormat->mLocator;
386acd88797a1d3b8225bab888d29036e245f275be5Glenn Kasten    pDataLocatorFormat->u.mSource.pFormat = &pDataLocatorFormat->mFormat;
387daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    return SL_RESULT_SUCCESS;
388daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten}
389daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten
390daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn KastenSLresult checkDataSink(const SLDataSink *pDataSink, DataLocatorFormat *pDataLocatorFormat)
391daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten{
392daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    if (NULL == pDataSink)
393daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
394daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    SLDataSink myDataSink = *pDataSink;
395daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    SLresult result;
396daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    result = checkDataLocator(myDataSink.pLocator, &pDataLocatorFormat->mLocator);
397daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    if (SL_RESULT_SUCCESS != result)
398daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        return result;
399daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    result = checkDataFormat(myDataSink.pFormat, &pDataLocatorFormat->mFormat);
400daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    if (SL_RESULT_SUCCESS != result) {
401daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        freeDataLocator(&pDataLocatorFormat->mLocator);
402daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        return result;
403daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    }
404acd88797a1d3b8225bab888d29036e245f275be5Glenn Kasten    pDataLocatorFormat->u.mSink.pLocator = &pDataLocatorFormat->mLocator;
405acd88797a1d3b8225bab888d29036e245f275be5Glenn Kasten    pDataLocatorFormat->u.mSink.pFormat = &pDataLocatorFormat->mFormat;
406daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    return SL_RESULT_SUCCESS;
407daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten}
408daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten
409daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kastenvoid freeDataLocatorFormat(DataLocatorFormat *dlf)
410daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten{
411daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    freeDataLocator(&dlf->mLocator);
412daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    freeDataFormat(&dlf->mFormat);
413daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten}
414daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten
41561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten/* Interface initialization hooks */
4162045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten
417a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kastenextern void
418a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    I3DCommit_init(void *),
419a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    I3DDoppler_init(void *),
420a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    I3DGrouping_init(void *),
421a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    I3DLocation_init(void *),
422a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    I3DMacroscopic_init(void *),
423a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    I3DSource_init(void *),
42461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IAudioDecoderCapabilities_init(void *),
42561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IAudioEncoderCapabilities_init(void *),
42661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IAudioEncoder_init(void *),
42761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IAudioIODeviceCapabilities_init(void *),
428a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IBassBoost_init(void *),
4290b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IBufferQueue_init(void *),
43061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IDeviceVolume_init(void *),
43161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IDynamicInterfaceManagement_init(void *),
43261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IDynamicSource_init(void *),
43361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IEffectSend_init(void *),
4340b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IEngineCapabilities_init(void *),
4350b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IEngine_init(void *),
436a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IEnvironmentalReverb_init(void *),
437a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IEqualizer_init(void *),
43861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    ILEDArray_init(void *),
4390b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IMIDIMessage_init(void *),
4400b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IMIDIMuteSolo_init(void *),
4410b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IMIDITempo_init(void *),
4420b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IMIDITime_init(void *),
44361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IMetadataExtraction_init(void *),
44461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IMetadataTraversal_init(void *),
44561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IMuteSolo_init(void *),
44661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IObject_init(void *),
4470b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IOutputMix_init(void *),
44861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IPitch_init(void *),
4490b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IPlay_init(void *),
45061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IPlaybackRate_init(void *),
45161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IPrefetchStatus_init(void *),
452a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IPresetReverb_init(void *),
45361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IRatePitch_init(void *),
45461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IRecord_init(void *),
4550b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    ISeek_init(void *),
45661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IThreadSync_init(void *),
45761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IVibra_init(void *),
458a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IVirtualizer_init(void *),
4590b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IVisualization_init(void *),
4600b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IVolume_init(void *);
461a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten
462b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten#ifdef USE_OUTPUTMIXEXT
463b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kastenextern void
464b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    IOutputMixExt_init(void *);
465b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten#endif
466b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten
46761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten/*static*/ const struct MPH_init MPH_init_table[MPH_MAX] = {
468510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_3DCOMMIT, */ I3DCommit_init, NULL, NULL },
469510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_3DDOPPLER, */ I3DDoppler_init, NULL, NULL },
470510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_3DGROUPING, */ I3DGrouping_init, NULL, NULL },
471510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_3DLOCATION, */ I3DLocation_init, NULL, NULL },
472510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_3DMACROSCOPIC, */ I3DMacroscopic_init, NULL, NULL },
473510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_3DSOURCE, */ I3DSource_init, NULL, NULL },
474510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_AUDIODECODERCAPABILITIES, */ IAudioDecoderCapabilities_init, NULL, NULL },
475510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_AUDIOENCODER, */ IAudioEncoder_init, NULL, NULL },
476510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_AUDIOENCODERCAPABILITIES, */ IAudioEncoderCapabilities_init, NULL, NULL },
477510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_AUDIOIODEVICECAPABILITIES, */ IAudioIODeviceCapabilities_init, NULL, NULL },
478510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_BASSBOOST, */ IBassBoost_init, NULL, NULL },
479510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_BUFFERQUEUE, */ IBufferQueue_init, NULL, NULL },
480510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_DEVICEVOLUME, */ IDeviceVolume_init, NULL, NULL },
481510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_DYNAMICINTERFACEMANAGEMENT, */ IDynamicInterfaceManagement_init, NULL, NULL },
482510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_DYNAMICSOURCE, */ IDynamicSource_init, NULL, NULL },
483510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_EFFECTSEND, */ IEffectSend_init, NULL, NULL },
484510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_ENGINE, */ IEngine_init, NULL, NULL },
485510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_ENGINECAPABILITIES, */ IEngineCapabilities_init, NULL, NULL },
486510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_ENVIRONMENTALREVERB, */ IEnvironmentalReverb_init, NULL, NULL },
487510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_EQUALIZER, */ IEqualizer_init, NULL, NULL },
488510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_LED, */ ILEDArray_init, NULL, NULL },
489510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_METADATAEXTRACTION, */ IMetadataExtraction_init, NULL, NULL },
490510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_METADATATRAVERSAL, */ IMetadataTraversal_init, NULL, NULL },
491510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_MIDIMESSAGE, */ IMIDIMessage_init, NULL, NULL },
492510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_MIDITIME, */ IMIDITime_init, NULL, NULL },
493510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_MIDITEMPO, */ IMIDITempo_init, NULL, NULL },
494510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_MIDIMUTESOLO, */ IMIDIMuteSolo_init, NULL, NULL },
495510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_MUTESOLO, */ IMuteSolo_init, NULL, NULL },
496510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_NULL, */ NULL, NULL, NULL },
497510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_OBJECT, */ IObject_init, NULL, NULL },
498510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_OUTPUTMIX, */ IOutputMix_init, NULL, NULL },
499510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_PITCH, */ IPitch_init, NULL, NULL },
500510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_PLAY, */ IPlay_init, NULL, NULL },
501510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_PLAYBACKRATE, */ IPlaybackRate_init, NULL, NULL },
502510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_PREFETCHSTATUS, */ IPrefetchStatus_init, NULL, NULL },
503510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_PRESETREVERB, */ IPresetReverb_init, NULL, NULL },
504510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_RATEPITCH, */ IRatePitch_init, NULL, NULL },
505510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_RECORD, */ IRecord_init, NULL, NULL },
506510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_SEEK, */ ISeek_init, NULL, NULL },
507510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_THREADSYNC, */ IThreadSync_init, NULL, NULL },
508510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_VIBRA, */ IVibra_init, NULL, NULL },
509510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_VIRTUALIZER, */ IVirtualizer_init, NULL, NULL },
510510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_VISUALIZATION, */ IVisualization_init, NULL, NULL },
511510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    { /* MPH_VOLUME, */ IVolume_init, NULL, NULL },
512bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    { /* MPH_OUTPUTMIXEXT, */
513bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#ifdef USE_OUTPUTMIXEXT
514510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        IOutputMixExt_init, NULL, NULL
515bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#else
516510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        NULL, NULL, NULL
517bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#endif
518bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        }
519bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten};
520bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
521bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten// Construct a new instance of the specified class, exposing selected interfaces
522bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
523ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn KastenIObject *construct(const ClassTable *class__, unsigned exposedMask, SLEngineItf engine)
524bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{
52572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    IObject *this;
52672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten    this = (IObject *) calloc(1, class__->mSize);
527bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    if (NULL != this) {
52872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        unsigned lossOfControlMask = 0;
529ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten        // a NULL engine means we are constructing the engine
53072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        IEngine *thisEngine = (IEngine *) engine;
531d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten        if (NULL == thisEngine) {
53272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten            thisEngine = &((CEngine *) this)->mEngine;
533d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten        } else {
534ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten            interface_lock_exclusive(thisEngine);
535d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten            if (MAX_INSTANCE <= thisEngine->mInstanceCount) {
536ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten                // too many objects
537ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten                interface_unlock_exclusive(thisEngine);
538d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten                free(this);
539ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten                return NULL;
540ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten            }
541d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten            // pre-allocate a pending slot, but don't assign bit from mInstanceMask yet
542ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten            ++thisEngine->mInstanceCount;
543d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten            assert(((unsigned) ~0) != thisEngine->mInstanceMask);
544ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten            interface_unlock_exclusive(thisEngine);
545ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten            // const, no lock needed
546ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten            if (thisEngine->mLossOfControlGlobal)
547ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten                lossOfControlMask = ~0;
548ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten        }
54972a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten        this->mLossOfControlMask = lossOfControlMask;
550ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten        this->mClass = class__;
551ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten        this->mEngine = thisEngine;
552bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        const struct iid_vtable *x = class__->mInterfaces;
553510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        SLuint8 *interfaceStateP = this->mInterfaceStates;
554510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        SLuint32 index;
555510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        for (index = 0; index < class__->mInterfaceCount; ++index, ++x, exposedMask >>= 1) {
556510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            SLuint32 state;
557bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten            if (exposedMask & 1) {
55883f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten                void *self = (char *) this + x->mOffset;
559d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten                // IObject does not have an mThis, so [1] is not always defined
560d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten                if (index)
561d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten                    ((IObject **) self)[1] = this;
56283f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten                VoidHook init = MPH_init_table[x->mMPH].mInit;
563bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten                if (NULL != init)
564bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten                    (*init)(self);
565510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten                state = INTERFACE_EXPOSED;
566510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            } else
567510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten                state = INTERFACE_UNINITIALIZED;
568510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            *interfaceStateP++ = state;
569bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten        }
570ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten        // only expose new object to sync thread after it is fully initialized
571ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten        interface_lock_exclusive(thisEngine);
572d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten        unsigned availMask = ~thisEngine->mInstanceMask;
573d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten        assert(availMask);
574d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten        unsigned i = ctz(availMask);
575d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten        assert(MAX_INSTANCE > i);
576d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten        assert(NULL == thisEngine->mInstances[i]);
577d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten        thisEngine->mInstances[i] = this;
578d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten        thisEngine->mInstanceMask |= 1 << i;
579d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten        // avoid zero as a valid instance ID
580d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten        this->mInstanceID = i + 1;
58100d2d554e04ac369367c903dbf53b975355d1bcdGlenn Kasten#ifdef USE_SDL
58200d2d554e04ac369367c903dbf53b975355d1bcdGlenn Kasten        SLboolean unpause = SL_BOOLEAN_FALSE;
58300d2d554e04ac369367c903dbf53b975355d1bcdGlenn Kasten        if (SL_OBJECTID_OUTPUTMIX == class__->mObjectID && NULL == thisEngine->mOutputMix) {
58400d2d554e04ac369367c903dbf53b975355d1bcdGlenn Kasten            thisEngine->mOutputMix = (COutputMix *) this;
58500d2d554e04ac369367c903dbf53b975355d1bcdGlenn Kasten            unpause = SL_BOOLEAN_TRUE;
58600d2d554e04ac369367c903dbf53b975355d1bcdGlenn Kasten        }
58700d2d554e04ac369367c903dbf53b975355d1bcdGlenn Kasten#endif
588ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten        interface_unlock_exclusive(thisEngine);
58900d2d554e04ac369367c903dbf53b975355d1bcdGlenn Kasten#ifdef USE_SDL
59000d2d554e04ac369367c903dbf53b975355d1bcdGlenn Kasten        if (unpause)
59100d2d554e04ac369367c903dbf53b975355d1bcdGlenn Kasten            SDL_PauseAudio(0);
59200d2d554e04ac369367c903dbf53b975355d1bcdGlenn Kasten#endif
593bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    }
594bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten    return this;
595bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}
596bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten
5970b167267bda99b68346045ccab14e810121d5de4Glenn Kasten/* Initial entry points */
598d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
5990b167267bda99b68346045ccab14e810121d5de4Glenn KastenSLresult SLAPIENTRY slCreateEngine(SLObjectItf *pEngine, SLuint32 numOptions,
6000b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    const SLEngineOption *pEngineOptions, SLuint32 numInterfaces,
6010b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired)
602d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
6036fff2c605cdc46a10037e011d8fb47702ae70c37Jean-Michel Trivi#ifdef USE_ANDROID
6046fff2c605cdc46a10037e011d8fb47702ae70c37Jean-Michel Trivi    android::ProcessState::self()->startThreadPool();
6056fff2c605cdc46a10037e011d8fb47702ae70c37Jean-Michel Trivi#endif
6060b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    if (NULL == pEngine)
607d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
6080b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    *pEngine = NULL;
6090b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    // default values
6100b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    SLboolean threadSafe = SL_BOOLEAN_TRUE;
6110b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    SLboolean lossOfControlGlobal = SL_BOOLEAN_FALSE;
6120b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    if (NULL != pEngineOptions) {
6130b167267bda99b68346045ccab14e810121d5de4Glenn Kasten        SLuint32 i;
6140b167267bda99b68346045ccab14e810121d5de4Glenn Kasten        const SLEngineOption *option = pEngineOptions;
6150b167267bda99b68346045ccab14e810121d5de4Glenn Kasten        for (i = 0; i < numOptions; ++i, ++option) {
6160b167267bda99b68346045ccab14e810121d5de4Glenn Kasten            switch (option->feature) {
6170b167267bda99b68346045ccab14e810121d5de4Glenn Kasten            case SL_ENGINEOPTION_THREADSAFE:
6180b167267bda99b68346045ccab14e810121d5de4Glenn Kasten                threadSafe = (SLboolean) option->data;
6190b167267bda99b68346045ccab14e810121d5de4Glenn Kasten                break;
6200b167267bda99b68346045ccab14e810121d5de4Glenn Kasten            case SL_ENGINEOPTION_LOSSOFCONTROL:
6210b167267bda99b68346045ccab14e810121d5de4Glenn Kasten                lossOfControlGlobal = (SLboolean) option->data;
6220b167267bda99b68346045ccab14e810121d5de4Glenn Kasten                break;
6230b167267bda99b68346045ccab14e810121d5de4Glenn Kasten            default:
6240b167267bda99b68346045ccab14e810121d5de4Glenn Kasten                return SL_RESULT_PARAMETER_INVALID;
6250b167267bda99b68346045ccab14e810121d5de4Glenn Kasten            }
6260b167267bda99b68346045ccab14e810121d5de4Glenn Kasten        }
62729b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten    }
6280b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    unsigned exposedMask;
629b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    const ClassTable *pCEngine_class = objectIDtoClass(SL_OBJECTID_ENGINE);
630b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    SLresult result = checkInterfaces(pCEngine_class, numInterfaces,
6310b167267bda99b68346045ccab14e810121d5de4Glenn Kasten        pInterfaceIds, pInterfaceRequired, &exposedMask);
6320b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    if (SL_RESULT_SUCCESS != result)
6330b167267bda99b68346045ccab14e810121d5de4Glenn Kasten        return result;
634b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    CEngine *this = (CEngine *) construct(pCEngine_class, exposedMask, NULL);
6350b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    if (NULL == this)
6360b167267bda99b68346045ccab14e810121d5de4Glenn Kasten        return SL_RESULT_MEMORY_FAILURE;
6370b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    this->mObject.mLossOfControlMask = lossOfControlGlobal ? ~0 : 0;
6380b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    this->mEngine.mLossOfControlGlobal = lossOfControlGlobal;
6390b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    this->mEngineCapabilities.mThreadSafe = threadSafe;
6400b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    *pEngine = &this->mObject.mItf;
641d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    return SL_RESULT_SUCCESS;
642d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
643d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
6440b167267bda99b68346045ccab14e810121d5de4Glenn KastenSLresult SLAPIENTRY slQueryNumSupportedEngineInterfaces(
6450b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    SLuint32 *pNumSupportedInterfaces)
646d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
6470b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    if (NULL == pNumSupportedInterfaces)
6482045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
649b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    const ClassTable *pCEngine_class = objectIDtoClass(SL_OBJECTID_ENGINE);
650b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    *pNumSupportedInterfaces = pCEngine_class->mInterfaceCount;
651d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    return SL_RESULT_SUCCESS;
652d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
653d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
6540b167267bda99b68346045ccab14e810121d5de4Glenn KastenSLresult SLAPIENTRY slQuerySupportedEngineInterfaces(SLuint32 index,
6550b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    SLInterfaceID *pInterfaceId)
656d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{
6570b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    if (NULL == pInterfaceId)
6582045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
659b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    const ClassTable *pCEngine_class = objectIDtoClass(SL_OBJECTID_ENGINE);
660b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    if (pCEngine_class->mInterfaceCount <= index)
661b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
662b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    *pInterfaceId = &SL_IID_array[pCEngine_class->mInterfaces[index].mMPH];
663d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten    return SL_RESULT_SUCCESS;
664d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}
665d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten
666d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten/* End */
667