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 22 static 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 #if USE_PROFILES & USE_PROFILES_OPTIONAL 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 if (NULL == pCLEDDevice_class) { 35 result = SL_RESULT_FEATURE_UNSUPPORTED; 36 } else { 37 result = checkInterfaces(pCLEDDevice_class, numInterfaces, pInterfaceIds, 38 pInterfaceRequired, &exposedMask); 39 } 40 if (SL_RESULT_SUCCESS == result) { 41 CLEDDevice *this = (CLEDDevice *) construct(pCLEDDevice_class, exposedMask, self); 42 if (NULL == this) { 43 result = SL_RESULT_MEMORY_FAILURE; 44 } else { 45 this->mDeviceID = deviceID; 46 IObject_Publish(&this->mObject); 47 // return the new LED object 48 *pDevice = &this->mObject.mItf; 49 } 50 } 51 } 52 #else 53 result = SL_RESULT_FEATURE_UNSUPPORTED; 54 #endif 55 56 SL_LEAVE_INTERFACE 57 } 58 59 60 static SLresult IEngine_CreateVibraDevice(SLEngineItf self, SLObjectItf *pDevice, SLuint32 deviceID, 61 SLuint32 numInterfaces, const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired) 62 { 63 SL_ENTER_INTERFACE 64 65 #if USE_PROFILES & USE_PROFILES_OPTIONAL 66 if ((NULL == pDevice) || (SL_DEFAULTDEVICEID_VIBRA != deviceID)) { 67 result = SL_RESULT_PARAMETER_INVALID; 68 } else { 69 *pDevice = NULL; 70 unsigned exposedMask; 71 const ClassTable *pCVibraDevice_class = objectIDtoClass(SL_OBJECTID_VIBRADEVICE); 72 if (NULL == pCVibraDevice_class) { 73 result = SL_RESULT_FEATURE_UNSUPPORTED; 74 } else { 75 result = checkInterfaces(pCVibraDevice_class, numInterfaces, 76 pInterfaceIds, pInterfaceRequired, &exposedMask); 77 } 78 if (SL_RESULT_SUCCESS == result) { 79 CVibraDevice *this = (CVibraDevice *) construct(pCVibraDevice_class, exposedMask, self); 80 if (NULL == this) { 81 result = SL_RESULT_MEMORY_FAILURE; 82 } else { 83 this->mDeviceID = deviceID; 84 IObject_Publish(&this->mObject); 85 // return the new vibra object 86 *pDevice = &this->mObject.mItf; 87 } 88 } 89 } 90 #else 91 result = SL_RESULT_FEATURE_UNSUPPORTED; 92 #endif 93 94 SL_LEAVE_INTERFACE 95 } 96 97 98 static SLresult IEngine_CreateAudioPlayer(SLEngineItf self, SLObjectItf *pPlayer, 99 SLDataSource *pAudioSrc, SLDataSink *pAudioSnk, SLuint32 numInterfaces, 100 const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired) 101 { 102 SL_ENTER_INTERFACE 103 104 if (NULL == pPlayer) { 105 result = SL_RESULT_PARAMETER_INVALID; 106 } else { 107 *pPlayer = NULL; 108 unsigned exposedMask; 109 const ClassTable *pCAudioPlayer_class = objectIDtoClass(SL_OBJECTID_AUDIOPLAYER); 110 assert(NULL != pCAudioPlayer_class); 111 result = checkInterfaces(pCAudioPlayer_class, numInterfaces, 112 pInterfaceIds, pInterfaceRequired, &exposedMask); 113 if (SL_RESULT_SUCCESS == result) { 114 115 // Construct our new AudioPlayer instance 116 CAudioPlayer *this = (CAudioPlayer *) construct(pCAudioPlayer_class, exposedMask, self); 117 if (NULL == this) { 118 result = SL_RESULT_MEMORY_FAILURE; 119 } else { 120 121 do { 122 123 // Initialize private fields not associated with an interface 124 125 // Default data source in case of failure in checkDataSource 126 this->mDataSource.mLocator.mLocatorType = SL_DATALOCATOR_NULL; 127 this->mDataSource.mFormat.mFormatType = SL_DATAFORMAT_NULL; 128 129 // Default data sink in case of failure in checkDataSink 130 this->mDataSink.mLocator.mLocatorType = SL_DATALOCATOR_NULL; 131 this->mDataSink.mFormat.mFormatType = SL_DATAFORMAT_NULL; 132 133 // Default is no per-channel mute or solo 134 this->mMuteMask = 0; 135 this->mSoloMask = 0; 136 137 // Will be set soon for PCM buffer queues, or later by platform-specific code 138 // during Realize or Prefetch 139 this->mNumChannels = 0; 140 this->mSampleRateMilliHz = 0; 141 142 // More default values, in case destructor needs to be called early 143 this->mDirectLevel = 0; 144 #ifdef USE_OUTPUTMIXEXT 145 this->mTrack = NULL; 146 this->mGains[0] = 1.0f; 147 this->mGains[1] = 1.0f; 148 this->mDestroyRequested = SL_BOOLEAN_FALSE; 149 #endif 150 #ifdef USE_SNDFILE 151 this->mSndFile.mPathname = NULL; 152 this->mSndFile.mSNDFILE = NULL; 153 memset(&this->mSndFile.mSfInfo, 0, sizeof(SF_INFO)); 154 memset(&this->mSndFile.mMutex, 0, sizeof(pthread_mutex_t)); 155 this->mSndFile.mEOF = SL_BOOLEAN_FALSE; 156 this->mSndFile.mWhich = 0; 157 memset(this->mSndFile.mBuffer, 0, sizeof(this->mSndFile.mBuffer)); 158 #endif 159 #ifdef ANDROID 160 // extra safe initializations of pointers, in case of incomplete construction 161 this->mpLock = NULL; 162 this->mAudioTrack = NULL; 163 // placement new (explicit constructor) 164 (void) new (&this->mSfPlayer) android::sp<android::SfPlayer>(); 165 (void) new (&this->mAuxEffect) android::sp<android::AudioEffect>(); 166 #endif 167 168 // Check the source and sink parameters against generic constraints, 169 // and make a local copy of all parameters in case other application threads 170 // change memory concurrently. 171 172 result = checkDataSource(pAudioSrc, &this->mDataSource); 173 if (SL_RESULT_SUCCESS != result) { 174 break; 175 } 176 177 result = checkDataSink(pAudioSnk, &this->mDataSink, SL_OBJECTID_AUDIOPLAYER); 178 if (SL_RESULT_SUCCESS != result) { 179 break; 180 } 181 182 // It would be unsafe to ever refer to the application pointers again 183 pAudioSrc = NULL; 184 pAudioSnk = NULL; 185 186 // Check that the requested interfaces are compatible with the data source 187 result = checkSourceFormatVsInterfacesCompatibility(&this->mDataSource, 188 pCAudioPlayer_class, exposedMask); 189 if (SL_RESULT_SUCCESS != result) { 190 break; 191 } 192 193 // copy the buffer queue count from source locator to the buffer queue interface 194 // we have already range-checked the value down to a smaller width 195 196 switch (this->mDataSource.mLocator.mLocatorType) { 197 case SL_DATALOCATOR_BUFFERQUEUE: 198 #ifdef ANDROID 199 case SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE: 200 #endif 201 this->mBufferQueue.mNumBuffers = 202 (SLuint16) this->mDataSource.mLocator.mBufferQueue.numBuffers; 203 assert(SL_DATAFORMAT_PCM == this->mDataSource.mFormat.mFormatType); 204 this->mNumChannels = this->mDataSource.mFormat.mPCM.numChannels; 205 this->mSampleRateMilliHz = this->mDataSource.mFormat.mPCM.samplesPerSec; 206 break; 207 default: 208 this->mBufferQueue.mNumBuffers = 0; 209 break; 210 } 211 212 // check the audio source and sink parameters against platform support 213 #ifdef ANDROID 214 result = android_audioPlayer_checkSourceSink(this); 215 if (SL_RESULT_SUCCESS != result) { 216 break; 217 } 218 #endif 219 220 #ifdef USE_SNDFILE 221 result = SndFile_checkAudioPlayerSourceSink(this); 222 if (SL_RESULT_SUCCESS != result) { 223 break; 224 } 225 #endif 226 227 #ifdef USE_OUTPUTMIXEXT 228 result = IOutputMixExt_checkAudioPlayerSourceSink(this); 229 if (SL_RESULT_SUCCESS != result) { 230 break; 231 } 232 #endif 233 234 // FIXME move to dedicated function 235 // Allocate memory for buffer queue 236 237 //if (0 != this->mBufferQueue.mNumBuffers) { 238 // inline allocation of circular mArray, up to a typical max 239 if (BUFFER_HEADER_TYPICAL >= this->mBufferQueue.mNumBuffers) { 240 this->mBufferQueue.mArray = this->mBufferQueue.mTypical; 241 } else { 242 // Avoid possible integer overflow during multiplication; this arbitrary 243 // maximum is big enough to not interfere with real applications, but 244 // small enough to not overflow. 245 if (this->mBufferQueue.mNumBuffers >= 256) { 246 result = SL_RESULT_MEMORY_FAILURE; 247 break; 248 } 249 this->mBufferQueue.mArray = (BufferHeader *) malloc((this->mBufferQueue. 250 mNumBuffers + 1) * sizeof(BufferHeader)); 251 if (NULL == this->mBufferQueue.mArray) { 252 result = SL_RESULT_MEMORY_FAILURE; 253 break; 254 } 255 } 256 this->mBufferQueue.mFront = this->mBufferQueue.mArray; 257 this->mBufferQueue.mRear = this->mBufferQueue.mArray; 258 //} 259 260 // used to store the data source of our audio player 261 this->mDynamicSource.mDataSource = &this->mDataSource.u.mSource; 262 263 // platform-specific initialization 264 #ifdef ANDROID 265 android_audioPlayer_create(this); 266 #endif 267 268 } while (0); 269 270 if (SL_RESULT_SUCCESS != result) { 271 IObject_Destroy(&this->mObject.mItf); 272 } else { 273 IObject_Publish(&this->mObject); 274 // return the new audio player object 275 *pPlayer = &this->mObject.mItf; 276 } 277 278 } 279 } 280 281 } 282 283 SL_LEAVE_INTERFACE 284 } 285 286 287 static SLresult IEngine_CreateAudioRecorder(SLEngineItf self, SLObjectItf *pRecorder, 288 SLDataSource *pAudioSrc, SLDataSink *pAudioSnk, SLuint32 numInterfaces, 289 const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired) 290 { 291 SL_ENTER_INTERFACE 292 293 #if (USE_PROFILES & USE_PROFILES_OPTIONAL) || defined(ANDROID) 294 if (NULL == pRecorder) { 295 result = SL_RESULT_PARAMETER_INVALID; 296 } else { 297 *pRecorder = NULL; 298 unsigned exposedMask; 299 const ClassTable *pCAudioRecorder_class = objectIDtoClass(SL_OBJECTID_AUDIORECORDER); 300 if (NULL == pCAudioRecorder_class) { 301 result = SL_RESULT_FEATURE_UNSUPPORTED; 302 } else { 303 result = checkInterfaces(pCAudioRecorder_class, numInterfaces, 304 pInterfaceIds, pInterfaceRequired, &exposedMask); 305 } 306 307 if (SL_RESULT_SUCCESS == result) { 308 309 // Construct our new AudioRecorder instance 310 CAudioRecorder *this = (CAudioRecorder *) construct(pCAudioRecorder_class, exposedMask, 311 self); 312 if (NULL == this) { 313 result = SL_RESULT_MEMORY_FAILURE; 314 } else { 315 316 do { 317 318 // Initialize fields not associated with any interface 319 320 // Default data source in case of failure in checkDataSource 321 this->mDataSource.mLocator.mLocatorType = SL_DATALOCATOR_NULL; 322 this->mDataSource.mFormat.mFormatType = SL_DATAFORMAT_NULL; 323 324 // Default data sink in case of failure in checkDataSink 325 this->mDataSink.mLocator.mLocatorType = SL_DATALOCATOR_NULL; 326 this->mDataSink.mFormat.mFormatType = SL_DATAFORMAT_NULL; 327 328 // These fields are set to real values by 329 // android_audioRecorder_checkSourceSinkSupport. Note that the data sink is 330 // always PCM buffer queue, so we know the channel count and sample rate early. 331 this->mNumChannels = 0; 332 this->mSampleRateMilliHz = 0; 333 #ifdef ANDROID 334 this->mAudioRecord = NULL; 335 this->mRecordSource = android::AUDIO_SOURCE_DEFAULT; 336 #endif 337 338 // Check the source and sink parameters, and make a local copy of all parameters 339 result = checkDataSource(pAudioSrc, &this->mDataSource); 340 if (SL_RESULT_SUCCESS != result) { 341 break; 342 } 343 result = checkDataSink(pAudioSnk, &this->mDataSink, SL_OBJECTID_AUDIORECORDER); 344 if (SL_RESULT_SUCCESS != result) { 345 break; 346 } 347 348 // It would be unsafe to ever refer to the application pointers again 349 pAudioSrc = NULL; 350 pAudioSnk = NULL; 351 352 // check the audio source and sink parameters against platform support 353 #ifdef ANDROID 354 result = android_audioRecorder_checkSourceSinkSupport(this); 355 if (SL_RESULT_SUCCESS != result) { 356 SL_LOGE("Cannot create AudioRecorder: invalid source or sink"); 357 break; 358 } 359 #endif 360 361 #ifdef ANDROID 362 // Allocate memory for buffer queue 363 SLuint32 locatorType = this->mDataSink.mLocator.mLocatorType; 364 if (locatorType == SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE) { 365 this->mBufferQueue.mNumBuffers = 366 this->mDataSink.mLocator.mBufferQueue.numBuffers; 367 // inline allocation of circular Buffer Queue mArray, up to a typical max 368 if (BUFFER_HEADER_TYPICAL >= this->mBufferQueue.mNumBuffers) { 369 this->mBufferQueue.mArray = this->mBufferQueue.mTypical; 370 } else { 371 // Avoid possible integer overflow during multiplication; this arbitrary 372 // maximum is big enough to not interfere with real applications, but 373 // small enough to not overflow. 374 if (this->mBufferQueue.mNumBuffers >= 256) { 375 result = SL_RESULT_MEMORY_FAILURE; 376 break; 377 } 378 this->mBufferQueue.mArray = (BufferHeader *) malloc((this->mBufferQueue. 379 mNumBuffers + 1) * sizeof(BufferHeader)); 380 if (NULL == this->mBufferQueue.mArray) { 381 result = SL_RESULT_MEMORY_FAILURE; 382 break; 383 } 384 } 385 this->mBufferQueue.mFront = this->mBufferQueue.mArray; 386 this->mBufferQueue.mRear = this->mBufferQueue.mArray; 387 } 388 #endif 389 390 // platform-specific initialization 391 #ifdef ANDROID 392 android_audioRecorder_create(this); 393 #endif 394 395 } while (0); 396 397 if (SL_RESULT_SUCCESS != result) { 398 IObject_Destroy(&this->mObject.mItf); 399 } else { 400 IObject_Publish(&this->mObject); 401 // return the new audio recorder object 402 *pRecorder = &this->mObject.mItf; 403 } 404 } 405 406 } 407 408 } 409 #else 410 result = SL_RESULT_FEATURE_UNSUPPORTED; 411 #endif 412 413 SL_LEAVE_INTERFACE 414 } 415 416 417 static SLresult IEngine_CreateMidiPlayer(SLEngineItf self, SLObjectItf *pPlayer, 418 SLDataSource *pMIDISrc, SLDataSource *pBankSrc, SLDataSink *pAudioOutput, 419 SLDataSink *pVibra, SLDataSink *pLEDArray, SLuint32 numInterfaces, 420 const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired) 421 { 422 SL_ENTER_INTERFACE 423 424 #if USE_PROFILES & (USE_PROFILES_GAME | USE_PROFILES_PHONE) 425 if ((NULL == pPlayer) || (NULL == pMIDISrc) || (NULL == pAudioOutput)) { 426 result = SL_RESULT_PARAMETER_INVALID; 427 } else { 428 *pPlayer = NULL; 429 unsigned exposedMask; 430 const ClassTable *pCMidiPlayer_class = objectIDtoClass(SL_OBJECTID_MIDIPLAYER); 431 if (NULL == pCMidiPlayer_class) { 432 result = SL_RESULT_FEATURE_UNSUPPORTED; 433 } else { 434 result = checkInterfaces(pCMidiPlayer_class, numInterfaces, 435 pInterfaceIds, pInterfaceRequired, &exposedMask); 436 } 437 if (SL_RESULT_SUCCESS == result) { 438 CMidiPlayer *this = (CMidiPlayer *) construct(pCMidiPlayer_class, exposedMask, self); 439 if (NULL == this) { 440 result = SL_RESULT_MEMORY_FAILURE; 441 } else { 442 // FIXME a fake value - why not use value from IPlay_init? what does CT check for? 443 this->mPlay.mDuration = 0; 444 IObject_Publish(&this->mObject); 445 // return the new MIDI player object 446 *pPlayer = &this->mObject.mItf; 447 } 448 } 449 } 450 #else 451 result = SL_RESULT_FEATURE_UNSUPPORTED; 452 #endif 453 454 SL_LEAVE_INTERFACE 455 } 456 457 458 static SLresult IEngine_CreateListener(SLEngineItf self, SLObjectItf *pListener, 459 SLuint32 numInterfaces, const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired) 460 { 461 SL_ENTER_INTERFACE 462 463 #if USE_PROFILES & USE_PROFILES_GAME 464 if (NULL == pListener) { 465 result = SL_RESULT_PARAMETER_INVALID; 466 } else { 467 *pListener = NULL; 468 unsigned exposedMask; 469 const ClassTable *pCListener_class = objectIDtoClass(SL_OBJECTID_LISTENER); 470 if (NULL == pCListener_class) { 471 result = SL_RESULT_FEATURE_UNSUPPORTED; 472 } else { 473 result = checkInterfaces(pCListener_class, numInterfaces, 474 pInterfaceIds, pInterfaceRequired, &exposedMask); 475 } 476 if (SL_RESULT_SUCCESS == result) { 477 CListener *this = (CListener *) construct(pCListener_class, exposedMask, self); 478 if (NULL == this) { 479 result = SL_RESULT_MEMORY_FAILURE; 480 } else { 481 IObject_Publish(&this->mObject); 482 // return the new 3D listener object 483 *pListener = &this->mObject.mItf; 484 } 485 } 486 } 487 #else 488 result = SL_RESULT_FEATURE_UNSUPPORTED; 489 #endif 490 491 SL_LEAVE_INTERFACE 492 } 493 494 495 static SLresult IEngine_Create3DGroup(SLEngineItf self, SLObjectItf *pGroup, SLuint32 numInterfaces, 496 const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired) 497 { 498 SL_ENTER_INTERFACE 499 500 #if USE_PROFILES & USE_PROFILES_GAME 501 if (NULL == pGroup) { 502 result = SL_RESULT_PARAMETER_INVALID; 503 } else { 504 *pGroup = NULL; 505 unsigned exposedMask; 506 const ClassTable *pC3DGroup_class = objectIDtoClass(SL_OBJECTID_3DGROUP); 507 if (NULL == pC3DGroup_class) { 508 result = SL_RESULT_FEATURE_UNSUPPORTED; 509 } else { 510 result = checkInterfaces(pC3DGroup_class, numInterfaces, 511 pInterfaceIds, pInterfaceRequired, &exposedMask); 512 } 513 if (SL_RESULT_SUCCESS == result) { 514 C3DGroup *this = (C3DGroup *) construct(pC3DGroup_class, exposedMask, self); 515 if (NULL == this) { 516 result = SL_RESULT_MEMORY_FAILURE; 517 } else { 518 this->mMemberMask = 0; 519 IObject_Publish(&this->mObject); 520 // return the new 3D group object 521 *pGroup = &this->mObject.mItf; 522 } 523 } 524 } 525 #else 526 result = SL_RESULT_FEATURE_UNSUPPORTED; 527 #endif 528 529 SL_LEAVE_INTERFACE 530 } 531 532 533 static SLresult IEngine_CreateOutputMix(SLEngineItf self, SLObjectItf *pMix, SLuint32 numInterfaces, 534 const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired) 535 { 536 SL_ENTER_INTERFACE 537 538 if (NULL == pMix) { 539 result = SL_RESULT_PARAMETER_INVALID; 540 } else { 541 *pMix = NULL; 542 unsigned exposedMask; 543 const ClassTable *pCOutputMix_class = objectIDtoClass(SL_OBJECTID_OUTPUTMIX); 544 assert(NULL != pCOutputMix_class); 545 result = checkInterfaces(pCOutputMix_class, numInterfaces, 546 pInterfaceIds, pInterfaceRequired, &exposedMask); 547 if (SL_RESULT_SUCCESS == result) { 548 COutputMix *this = (COutputMix *) construct(pCOutputMix_class, exposedMask, self); 549 if (NULL == this) { 550 result = SL_RESULT_MEMORY_FAILURE; 551 } else { 552 #ifdef ANDROID 553 android_outputMix_create(this); 554 #endif 555 #ifdef USE_SDL 556 IEngine *thisEngine = this->mObject.mEngine; 557 interface_lock_exclusive(thisEngine); 558 bool unpause = false; 559 if (NULL == thisEngine->mOutputMix) { 560 thisEngine->mOutputMix = this; 561 unpause = true; 562 } 563 interface_unlock_exclusive(thisEngine); 564 #endif 565 IObject_Publish(&this->mObject); 566 #ifdef USE_SDL 567 if (unpause) { 568 // Enable SDL_callback to be called periodically by SDL's internal thread 569 SDL_PauseAudio(0); 570 } 571 #endif 572 // return the new output mix object 573 *pMix = &this->mObject.mItf; 574 } 575 } 576 } 577 578 SL_LEAVE_INTERFACE 579 } 580 581 582 static SLresult IEngine_CreateMetadataExtractor(SLEngineItf self, SLObjectItf *pMetadataExtractor, 583 SLDataSource *pDataSource, SLuint32 numInterfaces, const SLInterfaceID *pInterfaceIds, 584 const SLboolean *pInterfaceRequired) 585 { 586 SL_ENTER_INTERFACE 587 588 #if USE_PROFILES & (USE_PROFILES_GAME | USE_PROFILES_MUSIC) 589 if (NULL == pMetadataExtractor) { 590 result = SL_RESULT_PARAMETER_INVALID; 591 } else { 592 *pMetadataExtractor = NULL; 593 unsigned exposedMask; 594 const ClassTable *pCMetadataExtractor_class = 595 objectIDtoClass(SL_OBJECTID_METADATAEXTRACTOR); 596 if (NULL == pCMetadataExtractor_class) { 597 result = SL_RESULT_FEATURE_UNSUPPORTED; 598 } else { 599 result = checkInterfaces(pCMetadataExtractor_class, numInterfaces, 600 pInterfaceIds, pInterfaceRequired, &exposedMask); 601 } 602 if (SL_RESULT_SUCCESS == result) { 603 CMetadataExtractor *this = (CMetadataExtractor *) 604 construct(pCMetadataExtractor_class, exposedMask, self); 605 if (NULL == this) { 606 result = SL_RESULT_MEMORY_FAILURE; 607 } else { 608 IObject_Publish(&this->mObject); 609 // return the new metadata extractor object 610 *pMetadataExtractor = &this->mObject.mItf; 611 result = SL_RESULT_SUCCESS; 612 } 613 } 614 } 615 #else 616 result = SL_RESULT_FEATURE_UNSUPPORTED; 617 #endif 618 619 SL_LEAVE_INTERFACE 620 } 621 622 623 static SLresult IEngine_CreateExtensionObject(SLEngineItf self, SLObjectItf *pObject, 624 void *pParameters, SLuint32 objectID, SLuint32 numInterfaces, 625 const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired) 626 { 627 SL_ENTER_INTERFACE 628 629 if (NULL == pObject) { 630 result = SL_RESULT_PARAMETER_INVALID; 631 } else { 632 *pObject = NULL; 633 result = SL_RESULT_FEATURE_UNSUPPORTED; 634 } 635 636 SL_LEAVE_INTERFACE 637 } 638 639 640 static SLresult IEngine_QueryNumSupportedInterfaces(SLEngineItf self, 641 SLuint32 objectID, SLuint32 *pNumSupportedInterfaces) 642 { 643 SL_ENTER_INTERFACE 644 645 if (NULL == pNumSupportedInterfaces) { 646 result = SL_RESULT_PARAMETER_INVALID; 647 } else { 648 const ClassTable *class__ = objectIDtoClass(objectID); 649 if (NULL == class__) { 650 result = SL_RESULT_FEATURE_UNSUPPORTED; 651 } else { 652 SLuint32 count = 0; 653 SLuint32 i; 654 for (i = 0; i < class__->mInterfaceCount; ++i) { 655 switch (class__->mInterfaces[i].mInterface) { 656 case INTERFACE_IMPLICIT: 657 case INTERFACE_IMPLICIT_PREREALIZE: 658 case INTERFACE_EXPLICIT: 659 case INTERFACE_EXPLICIT_PREREALIZE: 660 case INTERFACE_DYNAMIC: 661 ++count; 662 break; 663 case INTERFACE_UNAVAILABLE: 664 break; 665 default: 666 assert(false); 667 break; 668 } 669 } 670 *pNumSupportedInterfaces = count; 671 result = SL_RESULT_SUCCESS; 672 } 673 } 674 675 SL_LEAVE_INTERFACE; 676 } 677 678 679 static SLresult IEngine_QuerySupportedInterfaces(SLEngineItf self, 680 SLuint32 objectID, SLuint32 index, SLInterfaceID *pInterfaceId) 681 { 682 SL_ENTER_INTERFACE 683 684 if (NULL == pInterfaceId) { 685 result = SL_RESULT_PARAMETER_INVALID; 686 } else { 687 *pInterfaceId = NULL; 688 const ClassTable *class__ = objectIDtoClass(objectID); 689 if (NULL == class__) { 690 result = SL_RESULT_FEATURE_UNSUPPORTED; 691 } else { 692 result = SL_RESULT_PARAMETER_INVALID; // will be reset later 693 SLuint32 i; 694 for (i = 0; i < class__->mInterfaceCount; ++i) { 695 switch (class__->mInterfaces[i].mInterface) { 696 case INTERFACE_IMPLICIT: 697 case INTERFACE_IMPLICIT_PREREALIZE: 698 case INTERFACE_EXPLICIT: 699 case INTERFACE_EXPLICIT_PREREALIZE: 700 case INTERFACE_DYNAMIC: 701 break; 702 case INTERFACE_UNAVAILABLE: 703 continue; 704 default: 705 assert(false); 706 break; 707 } 708 if (index == 0) { 709 *pInterfaceId = &SL_IID_array[class__->mInterfaces[i].mMPH]; 710 result = SL_RESULT_SUCCESS; 711 break; 712 } 713 --index; 714 } 715 } 716 } 717 718 SL_LEAVE_INTERFACE 719 }; 720 721 722 static const char * const extensionNames[] = { 723 #ifdef ANDROID 724 "ANDROID_SDK_LEVEL_9", // Android 2.3 aka "Gingerbread" 725 // in the future, add more entries for each SDK level here, and 726 // don't delete the entries for previous SDK levels unless support is removed 727 #else 728 "WILHELM_DESKTOP", 729 #endif 730 }; 731 732 733 static SLresult IEngine_QueryNumSupportedExtensions(SLEngineItf self, SLuint32 *pNumExtensions) 734 { 735 SL_ENTER_INTERFACE 736 737 if (NULL == pNumExtensions) { 738 result = SL_RESULT_PARAMETER_INVALID; 739 } else { 740 *pNumExtensions = sizeof(extensionNames) / sizeof(extensionNames[0]); 741 result = SL_RESULT_SUCCESS; 742 } 743 744 SL_LEAVE_INTERFACE 745 } 746 747 748 static SLresult IEngine_QuerySupportedExtension(SLEngineItf self, 749 SLuint32 index, SLchar *pExtensionName, SLint16 *pNameLength) 750 { 751 SL_ENTER_INTERFACE 752 753 if (NULL == pNameLength) { 754 result = SL_RESULT_PARAMETER_INVALID; 755 } else { 756 size_t actualNameLength; 757 unsigned numExtensions = sizeof(extensionNames) / sizeof(extensionNames[0]); 758 if (index >= numExtensions) { 759 actualNameLength = 0; 760 result = SL_RESULT_PARAMETER_INVALID; 761 } else { 762 const char *extensionName = extensionNames[index]; 763 actualNameLength = strlen(extensionName) + 1; 764 if (NULL == pExtensionName) { 765 // application is querying the name length in order to allocate a buffer 766 result = SL_RESULT_SUCCESS; 767 } else { 768 SLint16 availableNameLength = *pNameLength; 769 if (0 >= availableNameLength) { 770 // there is not even room for the terminating NUL 771 result = SL_RESULT_BUFFER_INSUFFICIENT; 772 } else if (actualNameLength > (size_t) availableNameLength) { 773 // "no invalid strings are written. That is, the null-terminator always exists" 774 memcpy(pExtensionName, extensionName, (size_t) availableNameLength - 1); 775 pExtensionName[(size_t) availableNameLength - 1] = '\0'; 776 result = SL_RESULT_BUFFER_INSUFFICIENT; 777 } else { 778 memcpy(pExtensionName, extensionName, actualNameLength); 779 result = SL_RESULT_SUCCESS; 780 } 781 } 782 } 783 *pNameLength = actualNameLength; 784 } 785 786 SL_LEAVE_INTERFACE 787 } 788 789 790 static SLresult IEngine_IsExtensionSupported(SLEngineItf self, 791 const SLchar *pExtensionName, SLboolean *pSupported) 792 { 793 SL_ENTER_INTERFACE 794 795 if (NULL == pSupported) { 796 result = SL_RESULT_PARAMETER_INVALID; 797 } else { 798 SLboolean isSupported = SL_BOOLEAN_FALSE; 799 if (NULL == pExtensionName) { 800 result = SL_RESULT_PARAMETER_INVALID; 801 } else { 802 unsigned numExtensions = sizeof(extensionNames) / sizeof(extensionNames[0]); 803 unsigned i; 804 for (i = 0; i < numExtensions; ++i) { 805 if (!strcmp((const char *) pExtensionName, extensionNames[i])) { 806 isSupported = SL_BOOLEAN_TRUE; 807 break; 808 } 809 } 810 result = SL_RESULT_SUCCESS; 811 } 812 *pSupported = isSupported; 813 } 814 815 SL_LEAVE_INTERFACE 816 } 817 818 819 static const struct SLEngineItf_ IEngine_Itf = { 820 IEngine_CreateLEDDevice, 821 IEngine_CreateVibraDevice, 822 IEngine_CreateAudioPlayer, 823 IEngine_CreateAudioRecorder, 824 IEngine_CreateMidiPlayer, 825 IEngine_CreateListener, 826 IEngine_Create3DGroup, 827 IEngine_CreateOutputMix, 828 IEngine_CreateMetadataExtractor, 829 IEngine_CreateExtensionObject, 830 IEngine_QueryNumSupportedInterfaces, 831 IEngine_QuerySupportedInterfaces, 832 IEngine_QueryNumSupportedExtensions, 833 IEngine_QuerySupportedExtension, 834 IEngine_IsExtensionSupported 835 }; 836 837 void IEngine_init(void *self) 838 { 839 IEngine *this = (IEngine *) self; 840 this->mItf = &IEngine_Itf; 841 // mLossOfControlGlobal is initialized in slCreateEngine 842 #ifdef USE_SDL 843 this->mOutputMix = NULL; 844 #endif 845 this->mInstanceCount = 1; // ourself 846 this->mInstanceMask = 0; 847 this->mChangedMask = 0; 848 unsigned i; 849 for (i = 0; i < MAX_INSTANCE; ++i) { 850 this->mInstances[i] = NULL; 851 } 852 this->mShutdown = SL_BOOLEAN_FALSE; 853 this->mShutdownAck = SL_BOOLEAN_FALSE; 854 // mThreadPool is initialized in CEngine_Realize 855 memset(&this->mThreadPool, 0, sizeof(ThreadPool)); 856 #if defined(ANDROID) && !defined(USE_BACKPORT) 857 this->mEqNumPresets = 0; 858 this->mEqPresetNames = NULL; 859 #endif 860 } 861 862 void IEngine_deinit(void *self) 863 { 864 #if defined(ANDROID) && !defined(USE_BACKPORT) 865 IEngine *this = (IEngine *) self; 866 // free equalizer preset names 867 if (NULL != this->mEqPresetNames) { 868 for (unsigned i = 0; i < this->mEqNumPresets; ++i) { 869 if (NULL != this->mEqPresetNames[i]) { 870 delete[] this->mEqPresetNames[i]; 871 this->mEqPresetNames[i] = NULL; 872 } 873 } 874 delete[] this->mEqPresetNames; 875 this->mEqPresetNames = NULL; 876 } 877 this->mEqNumPresets = 0; 878 #endif 879 } 880