IEngine.c revision 4b65ef9efdf5aba01bea89d8cdd64f500560a28d
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                    // copy the buffer queue count from source locator to the buffer queue interface
138
139                    this->mBufferQueue.mNumBuffers = (SL_DATALOCATOR_BUFFERQUEUE == *(SLuint32 *)
140                        pAudioSrc->pLocator) ? ((SLDataLocator_BufferQueue *)
141                        pAudioSrc->pLocator)->numBuffers : 0;
142
143                    // check the audio source and sink parameters against platform support
144#ifdef ANDROID
145                    result = android_audioPlayer_checkSourceSink(this);
146                    if (SL_RESULT_SUCCESS != result)
147                        break;
148#endif
149
150#ifdef USE_SNDFILE
151                    result = SndFile_checkAudioPlayerSourceSink(this);
152                    if (SL_RESULT_SUCCESS != result)
153                        break;
154#endif
155
156#ifdef USE_OUTPUTMIXEXT
157                    result = IOutputMixExt_checkAudioPlayerSourceSink(this);
158                    if (SL_RESULT_SUCCESS != result)
159                        break;
160#endif
161
162                    // FIXME move to dedicated function
163                    // Allocate memory for buffer queue
164
165                    //if (0 != this->mBufferQueue.mNumBuffers) {
166                        // inline allocation of circular mArray, up to a typical max
167                        if (BUFFER_HEADER_TYPICAL >= this->mBufferQueue.mNumBuffers) {
168                            this->mBufferQueue.mArray = this->mBufferQueue.mTypical;
169                        } else {
170                            // Avoid possible integer overflow during multiplication; this arbitrary
171                            // maximum is big enough to not interfere with real applications, but
172                            // small enough to not overflow.
173                            if (this->mBufferQueue.mNumBuffers >= 256) {
174                                result = SL_RESULT_MEMORY_FAILURE;
175                                break;
176                            }
177                            this->mBufferQueue.mArray = (BufferHeader *) malloc((this->mBufferQueue.
178                                mNumBuffers + 1) * sizeof(BufferHeader));
179                            if (NULL == this->mBufferQueue.mArray) {
180                                result = SL_RESULT_MEMORY_FAILURE;
181                                break;
182                            }
183                        }
184                        this->mBufferQueue.mFront = this->mBufferQueue.mArray;
185                        this->mBufferQueue.mRear = this->mBufferQueue.mArray;
186                        //}
187
188                        // used to store the data source of our audio player
189                        this->mDynamicSource.mDataSource = &this->mDataSource.u.mSource;
190
191                        // platform-specific initialization
192#ifdef ANDROID
193                        android_audioPlayer_create(this);
194#endif
195
196                        // return the new audio player object
197                        *pPlayer = &this->mObject.mItf;
198
199                } while (0);
200
201                if (SL_RESULT_SUCCESS != result)
202                    (*this->mObject.mItf->Destroy)(&this->mObject.mItf);
203
204            }
205        }
206
207    }
208
209    SL_LEAVE_INTERFACE
210}
211
212
213static SLresult IEngine_CreateAudioRecorder(SLEngineItf self, SLObjectItf *pRecorder,
214    SLDataSource *pAudioSrc, SLDataSink *pAudioSnk, SLuint32 numInterfaces,
215    const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired)
216{
217    SL_ENTER_INTERFACE
218
219    SL_LOGV("IEngine_CreateAudioRecorder() entering");
220
221#if defined(USE_CONFORMANCE) || defined(ANDROID)
222    if (NULL == pRecorder) {
223        result = SL_RESULT_PARAMETER_INVALID;
224    } else {
225        *pRecorder = NULL;
226        unsigned exposedMask;
227        const ClassTable *pCAudioRecorder_class = objectIDtoClass(SL_OBJECTID_AUDIORECORDER);
228        result = checkInterfaces(pCAudioRecorder_class, numInterfaces,
229                pInterfaceIds, pInterfaceRequired, &exposedMask);
230
231        if (SL_RESULT_SUCCESS == result) {
232
233            // Construct our new AudioRecorder instance
234            CAudioRecorder *this = (CAudioRecorder *) construct(pCAudioRecorder_class, exposedMask,
235                    self);
236            if (NULL == this) {
237                result = SL_RESULT_MEMORY_FAILURE;
238            } else {
239
240                do {
241                    // Check the source and sink parameters, and make a local copy of all parameters
242                    result = checkDataSource(pAudioSrc, &this->mDataSource);
243                    if (SL_RESULT_SUCCESS != result)
244                        break;
245                    result = checkDataSink(pAudioSnk, &this->mDataSink);
246                    if (SL_RESULT_SUCCESS != result)
247                        break;
248
249                    // check the audio source and sink parameters against platform support
250#ifdef ANDROID
251                    result = android_audioRecorder_checkSourceSinkSupport(this);
252                    if (SL_RESULT_SUCCESS != result) {
253                        SL_LOGE("Android: Cannot create AudioRecorder: invalid source or sink");
254                        break;
255                    }
256#endif
257
258#ifdef ANDROID
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#endif
286
287
288
289                    // platform-specific initialization
290#ifdef ANDROID
291                    android_audioRecorder_create(this);
292#endif
293
294                    // return the new audio recorder object
295                    *pRecorder = &this->mObject.mItf;
296
297                } while (0);
298
299                if (SL_RESULT_SUCCESS != result)
300                    (*this->mObject.mItf->Destroy)(&this->mObject.mItf);
301            }
302
303        }
304
305    }
306#else
307    result = SL_RESULT_FEATURE_UNSUPPORTED;
308#endif
309
310    SL_LEAVE_INTERFACE
311}
312
313
314static SLresult IEngine_CreateMidiPlayer(SLEngineItf self, SLObjectItf *pPlayer,
315    SLDataSource *pMIDISrc, SLDataSource *pBankSrc, SLDataSink *pAudioOutput,
316    SLDataSink *pVibra, SLDataSink *pLEDArray, SLuint32 numInterfaces,
317    const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired)
318{
319    SL_ENTER_INTERFACE
320
321#ifdef USE_CONFORMANCE
322    if (NULL == pPlayer || NULL == pMIDISrc || NULL == pAudioOutput) {
323        result = SL_RESULT_PARAMETER_INVALID;
324    } else {
325        *pPlayer = NULL;
326        unsigned exposedMask;
327        const ClassTable *pCMidiPlayer_class = objectIDtoClass(SL_OBJECTID_MIDIPLAYER);
328        result = checkInterfaces(pCMidiPlayer_class, numInterfaces,
329            pInterfaceIds, pInterfaceRequired, &exposedMask);
330        if (SL_RESULT_SUCCESS == result) {
331            CMidiPlayer *this = (CMidiPlayer *) construct(pCMidiPlayer_class, exposedMask, self);
332            if (NULL == this) {
333                result = SL_RESULT_MEMORY_FAILURE;
334            } else {
335                // return the new MIDI player object
336                *pPlayer = &this->mObject.mItf;
337            }
338        }
339    }
340#else
341    result = SL_RESULT_FEATURE_UNSUPPORTED;
342#endif
343
344    SL_LEAVE_INTERFACE
345}
346
347
348static SLresult IEngine_CreateListener(SLEngineItf self, SLObjectItf *pListener,
349    SLuint32 numInterfaces, const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired)
350{
351    SL_ENTER_INTERFACE
352
353#ifdef USE_CONFORMANCE
354    if (NULL == pListener) {
355        result = SL_RESULT_PARAMETER_INVALID;
356    } else {
357        *pListener = NULL;
358        unsigned exposedMask;
359        const ClassTable *pCListener_class = objectIDtoClass(SL_OBJECTID_LISTENER);
360        result = checkInterfaces(pCListener_class, numInterfaces,
361            pInterfaceIds, pInterfaceRequired, &exposedMask);
362        if (SL_RESULT_SUCCESS == result) {
363            CListener *this = (CListener *) construct(pCListener_class, exposedMask, self);
364            if (NULL == this) {
365                result = SL_RESULT_MEMORY_FAILURE;
366            } else {
367                // return the new listener object
368                *pListener = &this->mObject.mItf;
369            }
370        }
371    }
372#else
373    result = SL_RESULT_FEATURE_UNSUPPORTED;
374#endif
375
376    SL_LEAVE_INTERFACE
377}
378
379
380static SLresult IEngine_Create3DGroup(SLEngineItf self, SLObjectItf *pGroup, SLuint32 numInterfaces,
381    const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired)
382{
383    SL_ENTER_INTERFACE
384
385#ifdef USE_CONFORMANCE
386    if (NULL == pGroup) {
387        result = SL_RESULT_PARAMETER_INVALID;
388    } else {
389        *pGroup = NULL;
390        unsigned exposedMask;
391        const ClassTable *pC3DGroup_class = objectIDtoClass(SL_OBJECTID_3DGROUP);
392        result = checkInterfaces(pC3DGroup_class, numInterfaces,
393            pInterfaceIds, pInterfaceRequired, &exposedMask);
394        if (SL_RESULT_SUCCESS == result) {
395            C3DGroup *this = (C3DGroup *) construct(pC3DGroup_class, exposedMask, self);
396            if (NULL == this) {
397                result = SL_RESULT_MEMORY_FAILURE;
398            } else {
399                this->mMemberMask = 0;
400                // return the new 3DGroup object
401                *pGroup = &this->mObject.mItf;
402            }
403        }
404    }
405#else
406    result = SL_RESULT_FEATURE_UNSUPPORTED;
407#endif
408
409    SL_LEAVE_INTERFACE
410}
411
412
413static SLresult IEngine_CreateOutputMix(SLEngineItf self, SLObjectItf *pMix, SLuint32 numInterfaces,
414    const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired)
415{
416    SL_ENTER_INTERFACE
417
418    if (NULL == pMix) {
419        result = SL_RESULT_PARAMETER_INVALID;
420    } else {
421        *pMix = NULL;
422        unsigned exposedMask;
423        const ClassTable *pCOutputMix_class = objectIDtoClass(SL_OBJECTID_OUTPUTMIX);
424        result = checkInterfaces(pCOutputMix_class, numInterfaces,
425            pInterfaceIds, pInterfaceRequired, &exposedMask);
426        if (SL_RESULT_SUCCESS == result) {
427            COutputMix *this = (COutputMix *) construct(pCOutputMix_class, exposedMask, self);
428            if (NULL == this) {
429                result = SL_RESULT_MEMORY_FAILURE;
430            } else {
431                *pMix = &this->mObject.mItf;
432            }
433        }
434    }
435
436    SL_LEAVE_INTERFACE
437}
438
439
440static SLresult IEngine_CreateMetadataExtractor(SLEngineItf self, SLObjectItf *pMetadataExtractor,
441    SLDataSource *pDataSource, SLuint32 numInterfaces, const SLInterfaceID *pInterfaceIds,
442    const SLboolean *pInterfaceRequired)
443{
444    SL_ENTER_INTERFACE
445
446#ifdef USE_CONFORMANCE
447    if (NULL == pMetadataExtractor) {
448        result = SL_RESULT_PARAMETER_INVALID;
449    } else {
450        *pMetadataExtractor = NULL;
451        unsigned exposedMask;
452        const ClassTable *pCMetadataExtractor_class =
453            objectIDtoClass(SL_OBJECTID_METADATAEXTRACTOR);
454        result = checkInterfaces(pCMetadataExtractor_class, numInterfaces,
455            pInterfaceIds, pInterfaceRequired, &exposedMask);
456        if (SL_RESULT_SUCCESS == result) {
457            CMetadataExtractor *this = (CMetadataExtractor *)
458                construct(pCMetadataExtractor_class, exposedMask, self);
459            if (NULL == this) {
460                result = SL_RESULT_MEMORY_FAILURE;
461            } else {
462                *pMetadataExtractor = &this->mObject.mItf;
463                result = SL_RESULT_SUCCESS;
464            }
465        }
466    }
467#else
468    result = SL_RESULT_FEATURE_UNSUPPORTED;
469#endif
470
471    SL_LEAVE_INTERFACE
472}
473
474
475static SLresult IEngine_CreateExtensionObject(SLEngineItf self, SLObjectItf *pObject,
476    void *pParameters, SLuint32 objectID, SLuint32 numInterfaces,
477    const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired)
478{
479    SL_ENTER_INTERFACE
480
481    if (NULL == pObject) {
482        result = SL_RESULT_PARAMETER_INVALID;
483    } else {
484        *pObject = NULL;
485        result = SL_RESULT_FEATURE_UNSUPPORTED;
486    }
487
488    SL_LEAVE_INTERFACE
489}
490
491
492static SLresult IEngine_QueryNumSupportedInterfaces(SLEngineItf self,
493    SLuint32 objectID, SLuint32 *pNumSupportedInterfaces)
494{
495    SL_ENTER_INTERFACE
496
497    if (NULL == pNumSupportedInterfaces) {
498        result = SL_RESULT_PARAMETER_INVALID;
499    } else {
500        const ClassTable *class__ = objectIDtoClass(objectID);
501        if (NULL == class__) {
502            result = SL_RESULT_FEATURE_UNSUPPORTED;
503        } else {
504            SLuint32 count = 0;
505            SLuint32 i;
506            for (i = 0; i < class__->mInterfaceCount; ++i)
507                if (class__->mInterfaces[i].mInterface != INTERFACE_UNAVAILABLE)
508                    ++count;
509            *pNumSupportedInterfaces = count;
510            result = SL_RESULT_SUCCESS;
511        }
512    }
513
514    SL_LEAVE_INTERFACE;
515}
516
517
518static SLresult IEngine_QuerySupportedInterfaces(SLEngineItf self,
519    SLuint32 objectID, SLuint32 index, SLInterfaceID *pInterfaceId)
520{
521    SL_ENTER_INTERFACE
522
523    if (NULL == pInterfaceId) {
524        result = SL_RESULT_PARAMETER_INVALID;
525    } else {
526        *pInterfaceId = NULL;
527        const ClassTable *class__ = objectIDtoClass(objectID);
528        if (NULL == class__) {
529            result = SL_RESULT_FEATURE_UNSUPPORTED;
530        } else {
531            result = SL_RESULT_PARAMETER_INVALID; // will be reset later
532            SLuint32 i;
533            for (i = 0; i < class__->mInterfaceCount; ++i) {
534                if (INTERFACE_UNAVAILABLE == class__->mInterfaces[i].mInterface)
535                    continue;
536                if (index == 0) {
537                    *pInterfaceId = &SL_IID_array[class__->mInterfaces[i].mMPH];
538                    result = SL_RESULT_SUCCESS;
539                    break;
540                }
541                --index;
542            }
543        }
544    }
545
546    SL_LEAVE_INTERFACE
547};
548
549
550static SLresult IEngine_QueryNumSupportedExtensions(SLEngineItf self, SLuint32 *pNumExtensions)
551{
552    SL_ENTER_INTERFACE
553
554    if (NULL == pNumExtensions) {
555        result = SL_RESULT_PARAMETER_INVALID;
556    } else {
557        *pNumExtensions = 0;
558        result = SL_RESULT_SUCCESS;
559    }
560
561    SL_LEAVE_INTERFACE
562}
563
564
565static SLresult IEngine_QuerySupportedExtension(SLEngineItf self,
566    SLuint32 index, SLchar *pExtensionName, SLint16 *pNameLength)
567{
568    SL_ENTER_INTERFACE
569
570    // any index >= 0 will be >= number of supported extensions
571    result = SL_RESULT_PARAMETER_INVALID;
572
573    SL_LEAVE_INTERFACE
574}
575
576
577static SLresult IEngine_IsExtensionSupported(SLEngineItf self,
578    const SLchar *pExtensionName, SLboolean *pSupported)
579{
580    SL_ENTER_INTERFACE
581
582    if (NULL == pExtensionName || NULL == pSupported) {
583        result = SL_RESULT_PARAMETER_INVALID;
584    } else {
585        // no extensions are supported
586        *pSupported = SL_BOOLEAN_FALSE;
587        result = SL_RESULT_SUCCESS;
588    }
589
590    SL_LEAVE_INTERFACE
591}
592
593
594static const struct SLEngineItf_ IEngine_Itf = {
595    IEngine_CreateLEDDevice,
596    IEngine_CreateVibraDevice,
597    IEngine_CreateAudioPlayer,
598    IEngine_CreateAudioRecorder,
599    IEngine_CreateMidiPlayer,
600    IEngine_CreateListener,
601    IEngine_Create3DGroup,
602    IEngine_CreateOutputMix,
603    IEngine_CreateMetadataExtractor,
604    IEngine_CreateExtensionObject,
605    IEngine_QueryNumSupportedInterfaces,
606    IEngine_QuerySupportedInterfaces,
607    IEngine_QueryNumSupportedExtensions,
608    IEngine_QuerySupportedExtension,
609    IEngine_IsExtensionSupported
610};
611
612void IEngine_init(void *self)
613{
614    IEngine *this = (IEngine *) self;
615    this->mItf = &IEngine_Itf;
616    // mLossOfControlGlobal is initialized in CreateEngine
617#ifdef USE_SDL
618    this->mOutputMix = NULL;
619#endif
620    this->mInstanceCount = 1; // ourself
621    this->mInstanceMask = 0;
622    this->mChangedMask = 0;
623    unsigned i;
624    for (i = 0; i < MAX_INSTANCE; ++i)
625        this->mInstances[i] = NULL;
626    this->mShutdown = SL_BOOLEAN_FALSE;
627    int ok;
628    ok = pthread_cond_init(&this->mShutdownCond, (const pthread_condattr_t *) NULL);
629    assert(0 == ok);
630#ifdef ANDROID
631    this->mEqNumPresets = 0;
632    this->mEqPresetNames = NULL;
633#endif
634}
635