IEngine.c revision 3af2a8dd03f3113d5da1000dd79c143a9f0c4f36
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/* Engine implementation */
18
19#include "sles_allinclusive.h"
20
21
22static SLresult IEngine_CreateLEDDevice(SLEngineItf self, SLObjectItf *pDevice, SLuint32 deviceID,
23    SLuint32 numInterfaces, const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired)
24{
25    SL_ENTER_INTERFACE
26
27#ifdef USE_CONFORMANCE
28    if (NULL == pDevice || SL_DEFAULTDEVICEID_LED != deviceID) {
29        result = SL_RESULT_PARAMETER_INVALID;
30    } else {
31        *pDevice = NULL;
32        unsigned exposedMask;
33        const ClassTable *pCLEDDevice_class = objectIDtoClass(SL_OBJECTID_LEDDEVICE);
34        result = checkInterfaces(pCLEDDevice_class, numInterfaces, pInterfaceIds,
35            pInterfaceRequired, &exposedMask);
36        if (SL_RESULT_SUCCESS == result) {
37            CLEDDevice *this = (CLEDDevice *) construct(pCLEDDevice_class, exposedMask, self);
38            if (NULL == this) {
39                result = SL_RESULT_MEMORY_FAILURE;
40            } else {
41                this->mDeviceID = deviceID;
42                *pDevice = &this->mObject.mItf;
43            }
44        }
45    }
46#else
47    result = SL_RESULT_FEATURE_UNSUPPORTED;
48#endif
49
50    SL_LEAVE_INTERFACE
51}
52
53
54static SLresult IEngine_CreateVibraDevice(SLEngineItf self, SLObjectItf *pDevice, SLuint32 deviceID,
55    SLuint32 numInterfaces, const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired)
56{
57    SL_ENTER_INTERFACE
58
59#ifdef USE_CONFORMANCE
60    if (NULL == pDevice || SL_DEFAULTDEVICEID_VIBRA != deviceID) {
61        result = SL_RESULT_PARAMETER_INVALID;
62    } else {
63        *pDevice = NULL;
64        unsigned exposedMask;
65        const ClassTable *pCVibraDevice_class = objectIDtoClass(SL_OBJECTID_VIBRADEVICE);
66        result = checkInterfaces(pCVibraDevice_class, numInterfaces,
67            pInterfaceIds, pInterfaceRequired, &exposedMask);
68        if (SL_RESULT_SUCCESS == result) {
69            CVibraDevice *this = (CVibraDevice *) construct(pCVibraDevice_class, exposedMask, self);
70            if (NULL == this) {
71                result = SL_RESULT_MEMORY_FAILURE;
72            } else {
73                this->mDeviceID = deviceID;
74                *pDevice = &this->mObject.mItf;
75            }
76        }
77    }
78#else
79    result = SL_RESULT_FEATURE_UNSUPPORTED;
80#endif
81
82    SL_LEAVE_INTERFACE
83}
84
85
86static SLresult IEngine_CreateAudioPlayer(SLEngineItf self, SLObjectItf *pPlayer,
87    SLDataSource *pAudioSrc, SLDataSink *pAudioSnk, SLuint32 numInterfaces,
88    const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired)
89{
90    SL_ENTER_INTERFACE
91
92    if (NULL == pPlayer) {
93       result = SL_RESULT_PARAMETER_INVALID;
94    } else {
95        *pPlayer = NULL;
96        unsigned exposedMask;
97        const ClassTable *pCAudioPlayer_class = objectIDtoClass(SL_OBJECTID_AUDIOPLAYER);
98        result = checkInterfaces(pCAudioPlayer_class, numInterfaces,
99            pInterfaceIds, pInterfaceRequired, &exposedMask);
100        if (SL_RESULT_SUCCESS == result) {
101
102            // Construct our new AudioPlayer instance
103            CAudioPlayer *this = (CAudioPlayer *) construct(pCAudioPlayer_class, exposedMask, self);
104            if (NULL == this) {
105                result = SL_RESULT_MEMORY_FAILURE;
106            } else {
107
108                do {
109
110                    // Initialize private fields not associated with an interface
111                    this->mMuteMask = 0;
112                    this->mSoloMask = 0;
113                    // const, will be set later by the containing AudioPlayer or MidiPlayer
114                    this->mNumChannels = 0;
115                    this->mSampleRateMilliHz = 0;
116
117                    // Check the source and sink parameters against generic constraints,
118                    // and make a local copy of all parameters in case other application threads
119                    // change memory concurrently.
120
121                    result = checkDataSource(pAudioSrc, &this->mDataSource);
122                    if (SL_RESULT_SUCCESS != result) {
123                        break;
124                    }
125
126                    result = checkSourceFormatVsInterfacesCompatibility(&this->mDataSource,
127                            numInterfaces, pInterfaceIds, pInterfaceRequired);
128                    if (SL_RESULT_SUCCESS != result) {
129                        break;
130                    }
131
132                    result = checkDataSink(pAudioSnk, &this->mDataSink);
133                    if (SL_RESULT_SUCCESS != result) {
134                        break;
135                    }
136
137                    // check the audio source and sink parameters against platform support
138#ifdef ANDROID
139                    result = sles_to_android_checkAudioPlayerSourceSink(this);
140                    if (SL_RESULT_SUCCESS != result)
141                        break;
142#else
143                    {
144                    // because we init buffer queues in SndFile below, which is not always present
145                    SLuint32 locatorType = *(SLuint32 *) pAudioSrc->pLocator;
146                    if (locatorType == SL_DATALOCATOR_BUFFERQUEUE)
147                        this->mBufferQueue.mNumBuffers = ((SLDataLocator_BufferQueue *)
148                            pAudioSrc->pLocator)->numBuffers;
149                    }
150#endif
151
152#ifdef USE_SNDFILE
153                    result = SndFile_checkAudioPlayerSourceSink(this);
154                    if (SL_RESULT_SUCCESS != result)
155                        break;
156#endif
157
158#ifdef USE_OUTPUTMIXEXT
159                    result = IOutputMixExt_checkAudioPlayerSourceSink(this);
160                    if (SL_RESULT_SUCCESS != result)
161                        break;
162#endif
163
164                    // FIXME move to dedicated function
165                    // Allocate memory for buffer queue
166                    //if (0 != this->mBufferQueue.mNumBuffers) {
167                        // inline allocation of circular mArray, up to a typical max
168                        if (BUFFER_HEADER_TYPICAL >= this->mBufferQueue.mNumBuffers) {
169                            this->mBufferQueue.mArray = this->mBufferQueue.mTypical;
170                        } else {
171                            // Avoid possible integer overflow during multiplication; this arbitrary
172                            // maximum is big enough to not interfere with real applications, but
173                            // small enough to not overflow.
174                            if (this->mBufferQueue.mNumBuffers >= 256) {
175                                result = SL_RESULT_MEMORY_FAILURE;
176                                break;
177                            }
178                            this->mBufferQueue.mArray = (BufferHeader *) malloc((this->mBufferQueue.
179                                mNumBuffers + 1) * sizeof(BufferHeader));
180                            if (NULL == this->mBufferQueue.mArray) {
181                                result = SL_RESULT_MEMORY_FAILURE;
182                                break;
183                            }
184                        }
185                        this->mBufferQueue.mFront = this->mBufferQueue.mArray;
186                        this->mBufferQueue.mRear = this->mBufferQueue.mArray;
187                        //}
188
189                        // used to store the data source of our audio player
190                        this->mDynamicSource.mDataSource = &this->mDataSource.u.mSource;
191
192                        // platform-specific initialization
193#ifdef ANDROID
194                        sles_to_android_audioPlayerCreate(this);
195#endif
196
197                        // return the new audio player object
198                        *pPlayer = &this->mObject.mItf;
199
200                } while (0);
201
202                if (SL_RESULT_SUCCESS != result)
203                    (*this->mObject.mItf->Destroy)(&this->mObject.mItf);
204
205            }
206        }
207
208    }
209
210    SL_LEAVE_INTERFACE
211}
212
213
214static SLresult IEngine_CreateAudioRecorder(SLEngineItf self, SLObjectItf *pRecorder,
215    SLDataSource *pAudioSrc, SLDataSink *pAudioSnk, SLuint32 numInterfaces,
216    const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired)
217{
218    SL_ENTER_INTERFACE
219
220    SL_LOGV("IEngine_CreateAudioRecorder() entering");
221
222#if defined(USE_CONFORMANCE) || defined(ANDROID)
223    if (NULL == pRecorder) {
224        result = SL_RESULT_PARAMETER_INVALID;
225    } else {
226        *pRecorder = NULL;
227        unsigned exposedMask;
228        const ClassTable *pCAudioRecorder_class = objectIDtoClass(SL_OBJECTID_AUDIORECORDER);
229        result = checkInterfaces(pCAudioRecorder_class, numInterfaces,
230                pInterfaceIds, pInterfaceRequired, &exposedMask);
231
232        if (SL_RESULT_SUCCESS == result) {
233
234            // Construct our new AudioRecorder instance
235            CAudioRecorder *this = (CAudioRecorder *) construct(pCAudioRecorder_class, exposedMask,
236                    self);
237            if (NULL == this) {
238                result = SL_RESULT_MEMORY_FAILURE;
239            } else {
240
241                do {
242                    // Check the source and sink parameters, and make a local copy of all parameters
243                    result = checkDataSource(pAudioSrc, &this->mDataSource);
244                    if (SL_RESULT_SUCCESS != result)
245                        break;
246                    result = checkDataSink(pAudioSnk, &this->mDataSink);
247                    if (SL_RESULT_SUCCESS != result)
248                        break;
249
250                    // check the audio source and sink parameters against platform support
251#ifdef ANDROID
252                    result = android_audioRecorder_checkSourceSinkSupport(this);
253                    if (SL_RESULT_SUCCESS != result) {
254                        SL_LOGE("Android: Cannot create AudioRecorder: invalid source or sink");
255                        break;
256                    }
257#endif
258
259                    // FIXME move to dedicated function
260                    SLuint32 locatorType = *(SLuint32 *) pAudioSnk->pLocator;
261                    if (locatorType == SL_DATALOCATOR_BUFFERQUEUE) {
262                        this->mBufferQueue.mNumBuffers = ((SLDataLocator_BufferQueue *)
263                                pAudioSnk->pLocator)->numBuffers;
264                        // inline allocation of circular Buffer Queue mArray, up to a typical max
265                        if (BUFFER_HEADER_TYPICAL >= this->mBufferQueue.mNumBuffers) {
266                            this->mBufferQueue.mArray = this->mBufferQueue.mTypical;
267                        } else {
268                            // Avoid possible integer overflow during multiplication; this arbitrary
269                            // maximum is big enough to not interfere with real applications, but
270                            // small enough to not overflow.
271                            if (this->mBufferQueue.mNumBuffers >= 256) {
272                                result = SL_RESULT_MEMORY_FAILURE;
273                                break;
274                            }
275                            this->mBufferQueue.mArray = (BufferHeader *) malloc((this->mBufferQueue.
276                                    mNumBuffers + 1) * sizeof(BufferHeader));
277                            if (NULL == this->mBufferQueue.mArray) {
278                                result = SL_RESULT_MEMORY_FAILURE;
279                                break;
280                            }
281                        }
282                        this->mBufferQueue.mFront = this->mBufferQueue.mArray;
283                        this->mBufferQueue.mRear = this->mBufferQueue.mArray;
284                    }
285
286
287
288                    // platform-specific initialization
289#ifdef ANDROID
290                    android_audioRecorder_create(this);
291#endif
292
293                    // return the new audio recorder object
294                    *pRecorder = &this->mObject.mItf;
295
296                } while (0);
297
298                if (SL_RESULT_SUCCESS != result)
299                    (*this->mObject.mItf->Destroy)(&this->mObject.mItf);
300            }
301
302        }
303
304    }
305#else
306    result = SL_RESULT_FEATURE_UNSUPPORTED;
307#endif
308
309    SL_LEAVE_INTERFACE
310}
311
312
313static SLresult IEngine_CreateMidiPlayer(SLEngineItf self, SLObjectItf *pPlayer,
314    SLDataSource *pMIDISrc, SLDataSource *pBankSrc, SLDataSink *pAudioOutput,
315    SLDataSink *pVibra, SLDataSink *pLEDArray, SLuint32 numInterfaces,
316    const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired)
317{
318    SL_ENTER_INTERFACE
319
320#ifdef USE_CONFORMANCE
321    if (NULL == pPlayer || NULL == pMIDISrc || NULL == pAudioOutput) {
322        result = SL_RESULT_PARAMETER_INVALID;
323    } else {
324        *pPlayer = NULL;
325        unsigned exposedMask;
326        const ClassTable *pCMidiPlayer_class = objectIDtoClass(SL_OBJECTID_MIDIPLAYER);
327        result = checkInterfaces(pCMidiPlayer_class, numInterfaces,
328            pInterfaceIds, pInterfaceRequired, &exposedMask);
329        if (SL_RESULT_SUCCESS == result) {
330            CMidiPlayer *this = (CMidiPlayer *) construct(pCMidiPlayer_class, exposedMask, self);
331            if (NULL == this) {
332                result = SL_RESULT_MEMORY_FAILURE;
333            } else {
334                // return the new MIDI player object
335                *pPlayer = &this->mObject.mItf;
336            }
337        }
338    }
339#else
340    result = SL_RESULT_FEATURE_UNSUPPORTED;
341#endif
342
343    SL_LEAVE_INTERFACE
344}
345
346
347static SLresult IEngine_CreateListener(SLEngineItf self, SLObjectItf *pListener,
348    SLuint32 numInterfaces, const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired)
349{
350    SL_ENTER_INTERFACE
351
352#ifdef USE_CONFORMANCE
353    if (NULL == pListener) {
354        result = SL_RESULT_PARAMETER_INVALID;
355    } else {
356        *pListener = NULL;
357        unsigned exposedMask;
358        const ClassTable *pCListener_class = objectIDtoClass(SL_OBJECTID_LISTENER);
359        result = checkInterfaces(pCListener_class, numInterfaces,
360            pInterfaceIds, pInterfaceRequired, &exposedMask);
361        if (SL_RESULT_SUCCESS == result) {
362            CListener *this = (CListener *) construct(pCListener_class, exposedMask, self);
363            if (NULL == this) {
364                result = SL_RESULT_MEMORY_FAILURE;
365            } else {
366                // return the new listener object
367                *pListener = &this->mObject.mItf;
368            }
369        }
370    }
371#else
372    result = SL_RESULT_FEATURE_UNSUPPORTED;
373#endif
374
375    SL_LEAVE_INTERFACE
376}
377
378
379static SLresult IEngine_Create3DGroup(SLEngineItf self, SLObjectItf *pGroup, SLuint32 numInterfaces,
380    const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired)
381{
382    SL_ENTER_INTERFACE
383
384#ifdef USE_CONFORMANCE
385    if (NULL == pGroup) {
386        result = SL_RESULT_PARAMETER_INVALID;
387    } else {
388        *pGroup = NULL;
389        unsigned exposedMask;
390        const ClassTable *pC3DGroup_class = objectIDtoClass(SL_OBJECTID_3DGROUP);
391        result = checkInterfaces(pC3DGroup_class, numInterfaces,
392            pInterfaceIds, pInterfaceRequired, &exposedMask);
393        if (SL_RESULT_SUCCESS == result) {
394            C3DGroup *this = (C3DGroup *) construct(pC3DGroup_class, exposedMask, self);
395            if (NULL == this) {
396                result = SL_RESULT_MEMORY_FAILURE;
397            } else {
398                this->mMemberMask = 0;
399                // return the new 3DGroup object
400                *pGroup = &this->mObject.mItf;
401            }
402        }
403    }
404#else
405    result = SL_RESULT_FEATURE_UNSUPPORTED;
406#endif
407
408    SL_LEAVE_INTERFACE
409}
410
411
412static SLresult IEngine_CreateOutputMix(SLEngineItf self, SLObjectItf *pMix, SLuint32 numInterfaces,
413    const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired)
414{
415    SL_ENTER_INTERFACE
416
417    if (NULL == pMix) {
418        result = SL_RESULT_PARAMETER_INVALID;
419    } else {
420        *pMix = NULL;
421        unsigned exposedMask;
422        const ClassTable *pCOutputMix_class = objectIDtoClass(SL_OBJECTID_OUTPUTMIX);
423        result = checkInterfaces(pCOutputMix_class, numInterfaces,
424            pInterfaceIds, pInterfaceRequired, &exposedMask);
425        if (SL_RESULT_SUCCESS == result) {
426            COutputMix *this = (COutputMix *) construct(pCOutputMix_class, exposedMask, self);
427            if (NULL == this) {
428                result = SL_RESULT_MEMORY_FAILURE;
429            } else {
430                *pMix = &this->mObject.mItf;
431            }
432        }
433    }
434
435    SL_LEAVE_INTERFACE
436}
437
438
439static SLresult IEngine_CreateMetadataExtractor(SLEngineItf self, SLObjectItf *pMetadataExtractor,
440    SLDataSource *pDataSource, SLuint32 numInterfaces, const SLInterfaceID *pInterfaceIds,
441    const SLboolean *pInterfaceRequired)
442{
443    SL_ENTER_INTERFACE
444
445#ifdef USE_CONFORMANCE
446    if (NULL == pMetadataExtractor) {
447        result = SL_RESULT_PARAMETER_INVALID;
448    } else {
449        *pMetadataExtractor = NULL;
450        unsigned exposedMask;
451        const ClassTable *pCMetadataExtractor_class =
452            objectIDtoClass(SL_OBJECTID_METADATAEXTRACTOR);
453        result = checkInterfaces(pCMetadataExtractor_class, numInterfaces,
454            pInterfaceIds, pInterfaceRequired, &exposedMask);
455        if (SL_RESULT_SUCCESS == result) {
456            CMetadataExtractor *this = (CMetadataExtractor *)
457                construct(pCMetadataExtractor_class, exposedMask, self);
458            if (NULL == this) {
459                result = SL_RESULT_MEMORY_FAILURE;
460            } else {
461                *pMetadataExtractor = &this->mObject.mItf;
462                result = SL_RESULT_SUCCESS;
463            }
464        }
465    }
466#else
467    result = SL_RESULT_FEATURE_UNSUPPORTED;
468#endif
469
470    SL_LEAVE_INTERFACE
471}
472
473
474static SLresult IEngine_CreateExtensionObject(SLEngineItf self, SLObjectItf *pObject,
475    void *pParameters, SLuint32 objectID, SLuint32 numInterfaces,
476    const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired)
477{
478    SL_ENTER_INTERFACE
479
480    if (NULL == pObject) {
481        result = SL_RESULT_PARAMETER_INVALID;
482    } else {
483        *pObject = NULL;
484        result = SL_RESULT_FEATURE_UNSUPPORTED;
485    }
486
487    SL_LEAVE_INTERFACE
488}
489
490
491static SLresult IEngine_QueryNumSupportedInterfaces(SLEngineItf self,
492    SLuint32 objectID, SLuint32 *pNumSupportedInterfaces)
493{
494    SL_ENTER_INTERFACE
495
496    if (NULL == pNumSupportedInterfaces) {
497        result = SL_RESULT_PARAMETER_INVALID;
498    } else {
499        const ClassTable *class__ = objectIDtoClass(objectID);
500        if (NULL == class__) {
501            result = SL_RESULT_FEATURE_UNSUPPORTED;
502        } else {
503            SLuint32 count = 0;
504            SLuint32 i;
505            for (i = 0; i < class__->mInterfaceCount; ++i)
506                if (class__->mInterfaces[i].mInterface != INTERFACE_UNAVAILABLE)
507                    ++count;
508            *pNumSupportedInterfaces = count;
509            result = SL_RESULT_SUCCESS;
510        }
511    }
512
513    SL_LEAVE_INTERFACE;
514}
515
516
517static SLresult IEngine_QuerySupportedInterfaces(SLEngineItf self,
518    SLuint32 objectID, SLuint32 index, SLInterfaceID *pInterfaceId)
519{
520    SL_ENTER_INTERFACE
521
522    if (NULL == pInterfaceId) {
523        result = SL_RESULT_PARAMETER_INVALID;
524    } else {
525        *pInterfaceId = NULL;
526        const ClassTable *class__ = objectIDtoClass(objectID);
527        if (NULL == class__) {
528            result = SL_RESULT_FEATURE_UNSUPPORTED;
529        } else {
530            result = SL_RESULT_PARAMETER_INVALID; // will be reset later
531            SLuint32 i;
532            for (i = 0; i < class__->mInterfaceCount; ++i) {
533                if (INTERFACE_UNAVAILABLE == class__->mInterfaces[i].mInterface)
534                    continue;
535                if (index == 0) {
536                    *pInterfaceId = &SL_IID_array[class__->mInterfaces[i].mMPH];
537                    result = SL_RESULT_SUCCESS;
538                    break;
539                }
540                --index;
541            }
542        }
543    }
544
545    SL_LEAVE_INTERFACE
546};
547
548
549static SLresult IEngine_QueryNumSupportedExtensions(SLEngineItf self, SLuint32 *pNumExtensions)
550{
551    SL_ENTER_INTERFACE
552
553    if (NULL == pNumExtensions) {
554        result = SL_RESULT_PARAMETER_INVALID;
555    } else {
556        *pNumExtensions = 0;
557        result = SL_RESULT_SUCCESS;
558    }
559
560    SL_LEAVE_INTERFACE
561}
562
563
564static SLresult IEngine_QuerySupportedExtension(SLEngineItf self,
565    SLuint32 index, SLchar *pExtensionName, SLint16 *pNameLength)
566{
567    SL_ENTER_INTERFACE
568
569    // any index >= 0 will be >= number of supported extensions
570    result = SL_RESULT_PARAMETER_INVALID;
571
572    SL_LEAVE_INTERFACE
573}
574
575
576static SLresult IEngine_IsExtensionSupported(SLEngineItf self,
577    const SLchar *pExtensionName, SLboolean *pSupported)
578{
579    SL_ENTER_INTERFACE
580
581    if (NULL == pExtensionName || NULL == pSupported) {
582        result = SL_RESULT_PARAMETER_INVALID;
583    } else {
584        // no extensions are supported
585        *pSupported = SL_BOOLEAN_FALSE;
586        result = SL_RESULT_SUCCESS;
587    }
588
589    SL_LEAVE_INTERFACE
590}
591
592
593static const struct SLEngineItf_ IEngine_Itf = {
594    IEngine_CreateLEDDevice,
595    IEngine_CreateVibraDevice,
596    IEngine_CreateAudioPlayer,
597    IEngine_CreateAudioRecorder,
598    IEngine_CreateMidiPlayer,
599    IEngine_CreateListener,
600    IEngine_Create3DGroup,
601    IEngine_CreateOutputMix,
602    IEngine_CreateMetadataExtractor,
603    IEngine_CreateExtensionObject,
604    IEngine_QueryNumSupportedInterfaces,
605    IEngine_QuerySupportedInterfaces,
606    IEngine_QueryNumSupportedExtensions,
607    IEngine_QuerySupportedExtension,
608    IEngine_IsExtensionSupported
609};
610
611void IEngine_init(void *self)
612{
613    IEngine *this = (IEngine *) self;
614    this->mItf = &IEngine_Itf;
615    // mLossOfControlGlobal is initialized in CreateEngine
616#ifdef USE_SDL
617    this->mOutputMix = NULL;
618#endif
619    this->mInstanceCount = 1; // ourself
620    this->mInstanceMask = 0;
621    this->mChangedMask = 0;
622    unsigned i;
623    for (i = 0; i < MAX_INSTANCE; ++i)
624        this->mInstances[i] = NULL;
625    this->mShutdown = SL_BOOLEAN_FALSE;
626    int ok;
627    ok = pthread_cond_init(&this->mShutdownCond, (const pthread_condattr_t *) NULL);
628    assert(0 == ok);
629#ifdef ANDROID
630    this->mEqNumPresets = 0;
631    this->mEqPresetNames = NULL;
632#endif
633}
634