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