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