entry.c revision 262059f71a68edc5e510427c63f5f1623d3672a8
1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/* Initial global entry points */
18
19#include "sles_allinclusive.h"
20
21
22/** \brief Internal code shared by slCreateEngine and xaCreateEngine */
23
24static SLresult liCreateEngine(SLObjectItf *pEngine, SLuint32 numOptions,
25    const SLEngineOption *pEngineOptions, SLuint32 numInterfaces,
26    const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired,
27    const ClassTable *pCEngine_class)
28{
29    SLresult result;
30
31    int ok;
32    ok = pthread_mutex_lock(&theOneTrueMutex);
33    assert(0 == ok);
34    bool needToUnlockTheOneTrueMutex = true;
35
36    do {
37
38        if (NULL == pEngine) {
39            result = SL_RESULT_PARAMETER_INVALID;
40            break;
41        }
42        *pEngine = NULL;
43
44        if ((0 < numOptions) && (NULL == pEngineOptions)) {
45            SL_LOGE("numOptions=%lu and pEngineOptions=NULL", numOptions);
46            result = SL_RESULT_PARAMETER_INVALID;
47            break;
48        }
49
50        // default values
51        SLboolean threadSafe = SL_BOOLEAN_TRUE;
52        SLboolean lossOfControlGlobal = SL_BOOLEAN_FALSE;
53
54        // process engine options
55        SLuint32 i;
56        const SLEngineOption *option = pEngineOptions;
57        result = SL_RESULT_SUCCESS;
58        for (i = 0; i < numOptions; ++i, ++option) {
59            switch (option->feature) {
60            case SL_ENGINEOPTION_THREADSAFE:
61                threadSafe = SL_BOOLEAN_FALSE != (SLboolean) option->data; // normalize
62                break;
63            case SL_ENGINEOPTION_LOSSOFCONTROL:
64                lossOfControlGlobal = SL_BOOLEAN_FALSE != (SLboolean) option->data; // normalize
65                break;
66            default:
67                SL_LOGE("unknown engine option: feature=%lu data=%lu",
68                    option->feature, option->data);
69                result = SL_RESULT_PARAMETER_INVALID;
70                break;
71            }
72        }
73        if (SL_RESULT_SUCCESS != result) {
74            break;
75        }
76
77        unsigned exposedMask;
78        assert(NULL != pCEngine_class);
79        result = checkInterfaces(pCEngine_class, numInterfaces,
80            pInterfaceIds, pInterfaceRequired, &exposedMask);
81        if (SL_RESULT_SUCCESS != result) {
82            break;
83        }
84
85        // if an engine already exists, then increment its ref count
86        CEngine *this = theOneTrueEngine;
87        if (NULL != this) {
88            assert(0 < theOneTrueRefCount);
89            ++theOneTrueRefCount;
90
91            // In order to update the engine object, we need to lock it,
92            // but that would violate the lock order and potentially deadlock.
93            // So we unlock now and note that it should not be unlocked later.
94            ok = pthread_mutex_unlock(&theOneTrueMutex);
95            assert(0 == ok);
96            needToUnlockTheOneTrueMutex = false;
97            object_lock_exclusive(&this->mObject);
98
99            // now expose additional interfaces not requested by the earlier engine create
100            const struct iid_vtable *x = pCEngine_class->mInterfaces;
101            SLuint8 *interfaceStateP = this->mObject.mInterfaceStates;
102            SLuint32 index;
103            for (index = 0; index < pCEngine_class->mInterfaceCount; ++index, ++x,
104                    exposedMask >>= 1, ++interfaceStateP) {
105                switch (*interfaceStateP) {
106                case INTERFACE_EXPOSED:         // previously exposed
107                    break;
108                case INTERFACE_INITIALIZED:     // not exposed during the earlier create
109                    if (exposedMask & 1) {
110                        const struct MPH_init *mi = &MPH_init_table[x->mMPH];
111                        BoolHook expose = mi->mExpose;
112                        if ((NULL == expose) || (*expose)((char *) this + x->mOffset)) {
113                            *interfaceStateP = INTERFACE_EXPOSED;
114                        }
115                        // FIXME log or report to application that expose hook failed
116                    }
117                    break;
118                case INTERFACE_UNINITIALIZED:   // no init hook
119                    break;
120                default:                        // impossible
121                    assert(false);
122                    break;
123                }
124            }
125            object_unlock_exclusive(&this->mObject);
126            // return the shared engine object
127            *pEngine = &this->mObject.mItf;
128            break;
129        }
130
131        // here when creating the first engine reference
132        assert(0 == theOneTrueRefCount);
133
134#ifdef ANDROID
135        android::ProcessState::self()->startThreadPool();
136        android::DataSource::RegisterDefaultSniffers();
137#endif
138
139        this = (CEngine *) construct(pCEngine_class, exposedMask, NULL);
140        if (NULL == this) {
141            result = SL_RESULT_MEMORY_FAILURE;
142            break;
143        }
144
145        // initialize fields not associated with an interface
146        // mThreadPool is initialized in CEngine_Realize
147        memset(&this->mThreadPool, 0, sizeof(ThreadPool));
148        memset(&this->mSyncThread, 0, sizeof(pthread_t));
149#if defined(ANDROID)
150        this->mEqNumPresets = 0;
151        this->mEqPresetNames = NULL;
152#endif
153        // initialize fields related to an interface
154        this->mObject.mLossOfControlMask = lossOfControlGlobal ? ~0 : 0;
155        this->mEngine.mLossOfControlGlobal = lossOfControlGlobal;
156        this->mEngineCapabilities.mThreadSafe = threadSafe;
157        IObject_Publish(&this->mObject);
158        theOneTrueEngine = this;
159        theOneTrueRefCount = 1;
160        // return the new engine object
161        *pEngine = &this->mObject.mItf;
162
163    } while(0);
164
165    if (needToUnlockTheOneTrueMutex) {
166        ok = pthread_mutex_unlock(&theOneTrueMutex);
167        assert(0 == ok);
168        needToUnlockTheOneTrueMutex = false;
169    }
170
171    return result;
172}
173
174
175/** \brief slCreateEngine Function */
176
177SL_API SLresult SLAPIENTRY slCreateEngine(SLObjectItf *pEngine, SLuint32 numOptions,
178    const SLEngineOption *pEngineOptions, SLuint32 numInterfaces,
179    const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired)
180{
181    SL_ENTER_GLOBAL
182
183    result = liCreateEngine(pEngine, numOptions, pEngineOptions, numInterfaces, pInterfaceIds,
184            pInterfaceRequired, objectIDtoClass(SL_OBJECTID_ENGINE));
185
186    SL_LEAVE_GLOBAL
187}
188
189
190/** Internal function for slQuerySupportedEngineInterfaces and xaQuerySupportedEngineInterfaces */
191
192static SLresult liQueryNumSupportedInterfaces(SLuint32 *pNumSupportedInterfaces,
193        const ClassTable *class__)
194{
195    SLresult result;
196    if (NULL == pNumSupportedInterfaces) {
197        result = SL_RESULT_PARAMETER_INVALID;
198    } else {
199        assert(NULL != class__);
200        SLuint32 count = 0;
201        SLuint32 i;
202        for (i = 0; i < class__->mInterfaceCount; ++i) {
203            switch (class__->mInterfaces[i].mInterface) {
204            case INTERFACE_IMPLICIT:
205            case INTERFACE_IMPLICIT_PREREALIZE:
206            case INTERFACE_EXPLICIT:
207            case INTERFACE_EXPLICIT_PREREALIZE:
208            case INTERFACE_DYNAMIC:
209                ++count;
210                break;
211            case INTERFACE_UNAVAILABLE:
212                break;
213            default:
214                assert(false);
215                break;
216            }
217        }
218        *pNumSupportedInterfaces = count;
219        result = SL_RESULT_SUCCESS;
220    }
221    return result;
222}
223
224
225/** \brief slQueryNumSupportedEngineInterfaces Function */
226
227SL_API SLresult SLAPIENTRY slQueryNumSupportedEngineInterfaces(SLuint32 *pNumSupportedInterfaces)
228{
229    SL_ENTER_GLOBAL
230
231    result = liQueryNumSupportedInterfaces(pNumSupportedInterfaces,
232            objectIDtoClass(SL_OBJECTID_ENGINE));
233
234    SL_LEAVE_GLOBAL
235}
236
237
238/** Internal function for slQuerySupportedEngineInterfaces and xaQuerySupportedEngineInterfaces */
239
240static SLresult liQuerySupportedInterfaces(SLuint32 index, SLInterfaceID *pInterfaceId,
241        const ClassTable *class__)
242{
243    SLresult result;
244    if (NULL == pInterfaceId) {
245        result = SL_RESULT_PARAMETER_INVALID;
246    } else {
247        *pInterfaceId = NULL;
248        assert(NULL != class__);
249        result = SL_RESULT_PARAMETER_INVALID;   // will be reset later
250        SLuint32 i;
251        for (i = 0; i < class__->mInterfaceCount; ++i) {
252            switch (class__->mInterfaces[i].mInterface) {
253            case INTERFACE_IMPLICIT:
254            case INTERFACE_IMPLICIT_PREREALIZE:
255            case INTERFACE_EXPLICIT:
256            case INTERFACE_EXPLICIT_PREREALIZE:
257            case INTERFACE_DYNAMIC:
258                break;
259            case INTERFACE_UNAVAILABLE:
260                continue;
261            default:
262                assert(false);
263                break;
264            }
265            if (index == 0) {
266                *pInterfaceId = &SL_IID_array[class__->mInterfaces[i].mMPH];
267                result = SL_RESULT_SUCCESS;
268                break;
269            }
270            --index;
271        }
272    }
273    return result;
274}
275
276
277/** \brief slQuerySupportedEngineInterfaces Function */
278
279SL_API SLresult SLAPIENTRY slQuerySupportedEngineInterfaces(SLuint32 index,
280        SLInterfaceID *pInterfaceId)
281{
282    SL_ENTER_GLOBAL
283
284    result = liQuerySupportedInterfaces(index, pInterfaceId, objectIDtoClass(SL_OBJECTID_ENGINE));
285
286    SL_LEAVE_GLOBAL
287}
288
289
290/** \brief xaCreateEngine Function */
291
292XA_API XAresult XAAPIENTRY xaCreateEngine(XAObjectItf *pEngine, XAuint32 numOptions,
293        const XAEngineOption *pEngineOptions, XAuint32 numInterfaces,
294        const XAInterfaceID *pInterfaceIds, const XAboolean *pInterfaceRequired)
295{
296    XA_ENTER_GLOBAL
297
298    result = liCreateEngine((SLObjectItf *) pEngine, numOptions,
299            (const SLEngineOption *) pEngineOptions, numInterfaces,
300            (const SLInterfaceID *) pInterfaceIds, (const SLboolean *) pInterfaceRequired,
301            objectIDtoClass(XA_OBJECTID_ENGINE));
302
303    XA_LEAVE_GLOBAL
304}
305
306
307/** \brief xaQueryNumSupportedEngineInterfaces Function */
308
309XA_API XAresult XAAPIENTRY xaQueryNumSupportedEngineInterfaces(XAuint32 *pNumSupportedInterfaces)
310{
311    XA_ENTER_GLOBAL
312
313    result = liQueryNumSupportedInterfaces(pNumSupportedInterfaces,
314            objectIDtoClass(XA_OBJECTID_ENGINE));
315
316    XA_LEAVE_GLOBAL
317}
318
319
320/** \brief xaQuerySupportedEngineInterfaces Function */
321
322XA_API XAresult XAAPIENTRY xaQuerySupportedEngineInterfaces(XAuint32 index,
323        XAInterfaceID *pInterfaceId)
324{
325    XA_ENTER_GLOBAL
326
327    result = liQuerySupportedInterfaces(index, (SLInterfaceID *) pInterfaceId,
328            objectIDtoClass(XA_OBJECTID_ENGINE));
329
330    XA_LEAVE_GLOBAL
331}
332