IEngine.c revision 2d427f091ef1cf6c1694e3ee5f3521166502a7b1
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#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 *thiz = (CLEDDevice *) construct(pCLEDDevice_class, exposedMask, self); 42 if (NULL == thiz) { 43 result = SL_RESULT_MEMORY_FAILURE; 44 } else { 45 thiz->mDeviceID = deviceID; 46 IObject_Publish(&thiz->mObject); 47 // return the new LED object 48 *pDevice = &thiz->mObject.mItf; 49 } 50 } 51 } 52#else 53 result = SL_RESULT_FEATURE_UNSUPPORTED; 54#endif 55 56 SL_LEAVE_INTERFACE 57} 58 59 60static 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 *thiz = (CVibraDevice *) construct(pCVibraDevice_class, exposedMask, self); 80 if (NULL == thiz) { 81 result = SL_RESULT_MEMORY_FAILURE; 82 } else { 83 thiz->mDeviceID = deviceID; 84 IObject_Publish(&thiz->mObject); 85 // return the new vibra object 86 *pDevice = &thiz->mObject.mItf; 87 } 88 } 89 } 90#else 91 result = SL_RESULT_FEATURE_UNSUPPORTED; 92#endif 93 94 SL_LEAVE_INTERFACE 95} 96 97 98static 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 *thiz = (CAudioPlayer *) construct(pCAudioPlayer_class, exposedMask, self); 117 if (NULL == thiz) { 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 thiz->mDataSource.mLocator.mLocatorType = SL_DATALOCATOR_NULL; 127 thiz->mDataSource.mFormat.mFormatType = SL_DATAFORMAT_NULL; 128 129 // Default data sink in case of failure in checkDataSink 130 thiz->mDataSink.mLocator.mLocatorType = SL_DATALOCATOR_NULL; 131 thiz->mDataSink.mFormat.mFormatType = SL_DATAFORMAT_NULL; 132 133 // Default is no per-channel mute or solo 134 thiz->mMuteMask = 0; 135 thiz->mSoloMask = 0; 136 137 // Will be set soon for PCM buffer queues, or later by platform-specific code 138 // during Realize or Prefetch 139 thiz->mNumChannels = 0; 140 thiz->mSampleRateMilliHz = 0; 141 142 // More default values, in case destructor needs to be called early 143 thiz->mDirectLevel = 0; 144#ifdef USE_OUTPUTMIXEXT 145 thiz->mTrack = NULL; 146 thiz->mGains[0] = 1.0f; 147 thiz->mGains[1] = 1.0f; 148 thiz->mDestroyRequested = SL_BOOLEAN_FALSE; 149#endif 150#ifdef USE_SNDFILE 151 thiz->mSndFile.mPathname = NULL; 152 thiz->mSndFile.mSNDFILE = NULL; 153 memset(&thiz->mSndFile.mSfInfo, 0, sizeof(SF_INFO)); 154 memset(&thiz->mSndFile.mMutex, 0, sizeof(pthread_mutex_t)); 155 thiz->mSndFile.mEOF = SL_BOOLEAN_FALSE; 156 thiz->mSndFile.mWhich = 0; 157 memset(thiz->mSndFile.mBuffer, 0, sizeof(thiz->mSndFile.mBuffer)); 158#endif 159#ifdef ANDROID 160 // extra safe initializations of pointers, in case of incomplete construction 161 thiz->mpLock = NULL; 162 thiz->mAudioTrack = NULL; 163 // placement new (explicit constructor) 164 (void) new (&thiz->mSfPlayer) android::sp<android::SfPlayer>(); 165 (void) new (&thiz->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", pAudioSrc, &thiz->mDataSource, 173 DATALOCATOR_MASK_URI | DATALOCATOR_MASK_ADDRESS | 174 DATALOCATOR_MASK_BUFFERQUEUE 175#ifdef ANDROID 176 | DATALOCATOR_MASK_ANDROIDFD | DATALOCATOR_MASK_ANDROIDSIMPLEBUFFERQUEUE 177 | DATALOCATOR_MASK_ANDROIDBUFFERQUEUE 178#endif 179 , DATAFORMAT_MASK_MIME | DATAFORMAT_MASK_PCM); 180 181 if (SL_RESULT_SUCCESS != result) { 182 break; 183 } 184 185 result = checkDataSink("pAudioSnk", pAudioSnk, &thiz->mDataSink, 186 DATALOCATOR_MASK_OUTPUTMIX, DATAFORMAT_MASK_NULL); 187 if (SL_RESULT_SUCCESS != result) { 188 break; 189 } 190 191 // It would be unsafe to ever refer to the application pointers again 192 pAudioSrc = NULL; 193 pAudioSnk = NULL; 194 195 // Check that the requested interfaces are compatible with the data source 196 result = checkSourceFormatVsInterfacesCompatibility(&thiz->mDataSource, 197 pCAudioPlayer_class, exposedMask); 198 if (SL_RESULT_SUCCESS != result) { 199 break; 200 } 201 202 // copy the buffer queue count from source locator to the buffer queue interface 203 // we have already range-checked the value down to a smaller width 204 205 switch (thiz->mDataSource.mLocator.mLocatorType) { 206 case SL_DATALOCATOR_BUFFERQUEUE: 207#ifdef ANDROID 208 case SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE: 209#endif 210 thiz->mBufferQueue.mNumBuffers = 211 (SLuint16) thiz->mDataSource.mLocator.mBufferQueue.numBuffers; 212 assert(SL_DATAFORMAT_PCM == thiz->mDataSource.mFormat.mFormatType); 213 thiz->mNumChannels = thiz->mDataSource.mFormat.mPCM.numChannels; 214 thiz->mSampleRateMilliHz = thiz->mDataSource.mFormat.mPCM.samplesPerSec; 215 break; 216 default: 217 thiz->mBufferQueue.mNumBuffers = 0; 218 break; 219 } 220 221 // check the audio source and sink parameters against platform support 222#ifdef ANDROID 223 result = android_audioPlayer_checkSourceSink(thiz); 224 if (SL_RESULT_SUCCESS != result) { 225 break; 226 } 227#endif 228 229#ifdef USE_SNDFILE 230 result = SndFile_checkAudioPlayerSourceSink(thiz); 231 if (SL_RESULT_SUCCESS != result) { 232 break; 233 } 234#endif 235 236#ifdef USE_OUTPUTMIXEXT 237 result = IOutputMixExt_checkAudioPlayerSourceSink(thiz); 238 if (SL_RESULT_SUCCESS != result) { 239 break; 240 } 241#endif 242 243 // Allocate memory for buffer queue 244 245 //if (0 != thiz->mBufferQueue.mNumBuffers) { 246 // inline allocation of circular mArray, up to a typical max 247 if (BUFFER_HEADER_TYPICAL >= thiz->mBufferQueue.mNumBuffers) { 248 thiz->mBufferQueue.mArray = thiz->mBufferQueue.mTypical; 249 } else { 250 // Avoid possible integer overflow during multiplication; this arbitrary 251 // maximum is big enough to not interfere with real applications, but 252 // small enough to not overflow. 253 if (thiz->mBufferQueue.mNumBuffers >= 256) { 254 result = SL_RESULT_MEMORY_FAILURE; 255 break; 256 } 257 thiz->mBufferQueue.mArray = (BufferHeader *) malloc((thiz->mBufferQueue. 258 mNumBuffers + 1) * sizeof(BufferHeader)); 259 if (NULL == thiz->mBufferQueue.mArray) { 260 result = SL_RESULT_MEMORY_FAILURE; 261 break; 262 } 263 } 264 thiz->mBufferQueue.mFront = thiz->mBufferQueue.mArray; 265 thiz->mBufferQueue.mRear = thiz->mBufferQueue.mArray; 266 //} 267 268 // used to store the data source of our audio player 269 thiz->mDynamicSource.mDataSource = &thiz->mDataSource.u.mSource; 270 271 // platform-specific initialization 272#ifdef ANDROID 273 android_audioPlayer_create(thiz); 274#endif 275 276 } while (0); 277 278 if (SL_RESULT_SUCCESS != result) { 279 IObject_Destroy(&thiz->mObject.mItf); 280 } else { 281 IObject_Publish(&thiz->mObject); 282 // return the new audio player object 283 *pPlayer = &thiz->mObject.mItf; 284 } 285 286 } 287 } 288 289 } 290 291 SL_LEAVE_INTERFACE 292} 293 294 295static SLresult IEngine_CreateAudioRecorder(SLEngineItf self, SLObjectItf *pRecorder, 296 SLDataSource *pAudioSrc, SLDataSink *pAudioSnk, SLuint32 numInterfaces, 297 const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired) 298{ 299 SL_ENTER_INTERFACE 300 301#if (USE_PROFILES & USE_PROFILES_OPTIONAL) || defined(ANDROID) 302 if (NULL == pRecorder) { 303 result = SL_RESULT_PARAMETER_INVALID; 304 } else { 305 *pRecorder = NULL; 306 unsigned exposedMask; 307 const ClassTable *pCAudioRecorder_class = objectIDtoClass(SL_OBJECTID_AUDIORECORDER); 308 if (NULL == pCAudioRecorder_class) { 309 result = SL_RESULT_FEATURE_UNSUPPORTED; 310 } else { 311 result = checkInterfaces(pCAudioRecorder_class, numInterfaces, 312 pInterfaceIds, pInterfaceRequired, &exposedMask); 313 } 314 315 if (SL_RESULT_SUCCESS == result) { 316 317 // Construct our new AudioRecorder instance 318 CAudioRecorder *thiz = (CAudioRecorder *) construct(pCAudioRecorder_class, exposedMask, 319 self); 320 if (NULL == thiz) { 321 result = SL_RESULT_MEMORY_FAILURE; 322 } else { 323 324 do { 325 326 // Initialize fields not associated with any interface 327 328 // Default data source in case of failure in checkDataSource 329 thiz->mDataSource.mLocator.mLocatorType = SL_DATALOCATOR_NULL; 330 thiz->mDataSource.mFormat.mFormatType = SL_DATAFORMAT_NULL; 331 332 // Default data sink in case of failure in checkDataSink 333 thiz->mDataSink.mLocator.mLocatorType = SL_DATALOCATOR_NULL; 334 thiz->mDataSink.mFormat.mFormatType = SL_DATAFORMAT_NULL; 335 336 // These fields are set to real values by 337 // android_audioRecorder_checkSourceSinkSupport. Note that the data sink is 338 // always PCM buffer queue, so we know the channel count and sample rate early. 339 thiz->mNumChannels = 0; 340 thiz->mSampleRateMilliHz = 0; 341#ifdef ANDROID 342 thiz->mAudioRecord = NULL; 343 thiz->mRecordSource = android::AUDIO_SOURCE_DEFAULT; 344#endif 345 346 // Check the source and sink parameters, and make a local copy of all parameters 347 result = checkDataSource("pAudioSrc", pAudioSrc, &thiz->mDataSource, 348 DATALOCATOR_MASK_IODEVICE, DATAFORMAT_MASK_NULL); 349 if (SL_RESULT_SUCCESS != result) { 350 break; 351 } 352 result = checkDataSink("pAudioSnk", pAudioSnk, &thiz->mDataSink, 353 DATALOCATOR_MASK_URI 354#ifdef ANDROID 355 | DATALOCATOR_MASK_ANDROIDSIMPLEBUFFERQUEUE 356#endif 357 , DATAFORMAT_MASK_MIME | DATAFORMAT_MASK_PCM 358 ); 359 if (SL_RESULT_SUCCESS != result) { 360 break; 361 } 362 363 // It would be unsafe to ever refer to the application pointers again 364 pAudioSrc = NULL; 365 pAudioSnk = NULL; 366 367 // check the audio source and sink parameters against platform support 368#ifdef ANDROID 369 result = android_audioRecorder_checkSourceSinkSupport(thiz); 370 if (SL_RESULT_SUCCESS != result) { 371 SL_LOGE("Cannot create AudioRecorder: invalid source or sink"); 372 break; 373 } 374#endif 375 376#ifdef ANDROID 377 // Allocate memory for buffer queue 378 SLuint32 locatorType = thiz->mDataSink.mLocator.mLocatorType; 379 if (locatorType == SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE) { 380 thiz->mBufferQueue.mNumBuffers = 381 thiz->mDataSink.mLocator.mBufferQueue.numBuffers; 382 // inline allocation of circular Buffer Queue mArray, up to a typical max 383 if (BUFFER_HEADER_TYPICAL >= thiz->mBufferQueue.mNumBuffers) { 384 thiz->mBufferQueue.mArray = thiz->mBufferQueue.mTypical; 385 } else { 386 // Avoid possible integer overflow during multiplication; this arbitrary 387 // maximum is big enough to not interfere with real applications, but 388 // small enough to not overflow. 389 if (thiz->mBufferQueue.mNumBuffers >= 256) { 390 result = SL_RESULT_MEMORY_FAILURE; 391 break; 392 } 393 thiz->mBufferQueue.mArray = (BufferHeader *) malloc((thiz->mBufferQueue. 394 mNumBuffers + 1) * sizeof(BufferHeader)); 395 if (NULL == thiz->mBufferQueue.mArray) { 396 result = SL_RESULT_MEMORY_FAILURE; 397 break; 398 } 399 } 400 thiz->mBufferQueue.mFront = thiz->mBufferQueue.mArray; 401 thiz->mBufferQueue.mRear = thiz->mBufferQueue.mArray; 402 } 403#endif 404 405 // platform-specific initialization 406#ifdef ANDROID 407 android_audioRecorder_create(thiz); 408#endif 409 410 } while (0); 411 412 if (SL_RESULT_SUCCESS != result) { 413 IObject_Destroy(&thiz->mObject.mItf); 414 } else { 415 IObject_Publish(&thiz->mObject); 416 // return the new audio recorder object 417 *pRecorder = &thiz->mObject.mItf; 418 } 419 } 420 421 } 422 423 } 424#else 425 result = SL_RESULT_FEATURE_UNSUPPORTED; 426#endif 427 428 SL_LEAVE_INTERFACE 429} 430 431 432static SLresult IEngine_CreateMidiPlayer(SLEngineItf self, SLObjectItf *pPlayer, 433 SLDataSource *pMIDISrc, SLDataSource *pBankSrc, SLDataSink *pAudioOutput, 434 SLDataSink *pVibra, SLDataSink *pLEDArray, SLuint32 numInterfaces, 435 const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired) 436{ 437 SL_ENTER_INTERFACE 438 439#if USE_PROFILES & (USE_PROFILES_GAME | USE_PROFILES_PHONE) 440 if ((NULL == pPlayer) || (NULL == pMIDISrc) || (NULL == pAudioOutput)) { 441 result = SL_RESULT_PARAMETER_INVALID; 442 } else { 443 *pPlayer = NULL; 444 unsigned exposedMask; 445 const ClassTable *pCMidiPlayer_class = objectIDtoClass(SL_OBJECTID_MIDIPLAYER); 446 if (NULL == pCMidiPlayer_class) { 447 result = SL_RESULT_FEATURE_UNSUPPORTED; 448 } else { 449 result = checkInterfaces(pCMidiPlayer_class, numInterfaces, 450 pInterfaceIds, pInterfaceRequired, &exposedMask); 451 } 452 if (SL_RESULT_SUCCESS == result) { 453 CMidiPlayer *thiz = (CMidiPlayer *) construct(pCMidiPlayer_class, exposedMask, self); 454 if (NULL == thiz) { 455 result = SL_RESULT_MEMORY_FAILURE; 456 } else { 457#if 0 458 "pMIDISrc", pMIDISrc, URI | MIDIBUFFERQUEUE, NONE 459 "pBankSrc", pBanksrc, NULL | URI | ADDRESS, NULL 460 "pAudioOutput", pAudioOutput, OUTPUTMIX, NULL 461 "pVibra", pVibra, NULL | IODEVICE, NULL 462 "pLEDArray", pLEDArray, NULL | IODEVICE, NULL 463#endif 464 // a fake value - why not use value from IPlay_init? what does CT check for? 465 thiz->mPlay.mDuration = 0; 466 IObject_Publish(&thiz->mObject); 467 // return the new MIDI player object 468 *pPlayer = &thiz->mObject.mItf; 469 } 470 } 471 } 472#else 473 result = SL_RESULT_FEATURE_UNSUPPORTED; 474#endif 475 476 SL_LEAVE_INTERFACE 477} 478 479 480static SLresult IEngine_CreateListener(SLEngineItf self, SLObjectItf *pListener, 481 SLuint32 numInterfaces, const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired) 482{ 483 SL_ENTER_INTERFACE 484 485#if USE_PROFILES & USE_PROFILES_GAME 486 if (NULL == pListener) { 487 result = SL_RESULT_PARAMETER_INVALID; 488 } else { 489 *pListener = NULL; 490 unsigned exposedMask; 491 const ClassTable *pCListener_class = objectIDtoClass(SL_OBJECTID_LISTENER); 492 if (NULL == pCListener_class) { 493 result = SL_RESULT_FEATURE_UNSUPPORTED; 494 } else { 495 result = checkInterfaces(pCListener_class, numInterfaces, 496 pInterfaceIds, pInterfaceRequired, &exposedMask); 497 } 498 if (SL_RESULT_SUCCESS == result) { 499 CListener *thiz = (CListener *) construct(pCListener_class, exposedMask, self); 500 if (NULL == thiz) { 501 result = SL_RESULT_MEMORY_FAILURE; 502 } else { 503 IObject_Publish(&thiz->mObject); 504 // return the new 3D listener object 505 *pListener = &thiz->mObject.mItf; 506 } 507 } 508 } 509#else 510 result = SL_RESULT_FEATURE_UNSUPPORTED; 511#endif 512 513 SL_LEAVE_INTERFACE 514} 515 516 517static SLresult IEngine_Create3DGroup(SLEngineItf self, SLObjectItf *pGroup, SLuint32 numInterfaces, 518 const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired) 519{ 520 SL_ENTER_INTERFACE 521 522#if USE_PROFILES & USE_PROFILES_GAME 523 if (NULL == pGroup) { 524 result = SL_RESULT_PARAMETER_INVALID; 525 } else { 526 *pGroup = NULL; 527 unsigned exposedMask; 528 const ClassTable *pC3DGroup_class = objectIDtoClass(SL_OBJECTID_3DGROUP); 529 if (NULL == pC3DGroup_class) { 530 result = SL_RESULT_FEATURE_UNSUPPORTED; 531 } else { 532 result = checkInterfaces(pC3DGroup_class, numInterfaces, 533 pInterfaceIds, pInterfaceRequired, &exposedMask); 534 } 535 if (SL_RESULT_SUCCESS == result) { 536 C3DGroup *thiz = (C3DGroup *) construct(pC3DGroup_class, exposedMask, self); 537 if (NULL == thiz) { 538 result = SL_RESULT_MEMORY_FAILURE; 539 } else { 540 thiz->mMemberMask = 0; 541 IObject_Publish(&thiz->mObject); 542 // return the new 3D group object 543 *pGroup = &thiz->mObject.mItf; 544 } 545 } 546 } 547#else 548 result = SL_RESULT_FEATURE_UNSUPPORTED; 549#endif 550 551 SL_LEAVE_INTERFACE 552} 553 554 555static SLresult IEngine_CreateOutputMix(SLEngineItf self, SLObjectItf *pMix, SLuint32 numInterfaces, 556 const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired) 557{ 558 SL_ENTER_INTERFACE 559 560 if (NULL == pMix) { 561 result = SL_RESULT_PARAMETER_INVALID; 562 } else { 563 *pMix = NULL; 564 unsigned exposedMask; 565 const ClassTable *pCOutputMix_class = objectIDtoClass(SL_OBJECTID_OUTPUTMIX); 566 assert(NULL != pCOutputMix_class); 567 result = checkInterfaces(pCOutputMix_class, numInterfaces, 568 pInterfaceIds, pInterfaceRequired, &exposedMask); 569 if (SL_RESULT_SUCCESS == result) { 570 COutputMix *thiz = (COutputMix *) construct(pCOutputMix_class, exposedMask, self); 571 if (NULL == thiz) { 572 result = SL_RESULT_MEMORY_FAILURE; 573 } else { 574#ifdef ANDROID 575 android_outputMix_create(thiz); 576#endif 577#ifdef USE_SDL 578 IEngine *thisEngine = &thiz->mObject.mEngine->mEngine; 579 interface_lock_exclusive(thisEngine); 580 bool unpause = false; 581 if (NULL == thisEngine->mOutputMix) { 582 thisEngine->mOutputMix = thiz; 583 unpause = true; 584 } 585 interface_unlock_exclusive(thisEngine); 586#endif 587 IObject_Publish(&thiz->mObject); 588#ifdef USE_SDL 589 if (unpause) { 590 // Enable SDL_callback to be called periodically by SDL's internal thread 591 SDL_PauseAudio(0); 592 } 593#endif 594 // return the new output mix object 595 *pMix = &thiz->mObject.mItf; 596 } 597 } 598 } 599 600 SL_LEAVE_INTERFACE 601} 602 603 604static SLresult IEngine_CreateMetadataExtractor(SLEngineItf self, SLObjectItf *pMetadataExtractor, 605 SLDataSource *pDataSource, SLuint32 numInterfaces, const SLInterfaceID *pInterfaceIds, 606 const SLboolean *pInterfaceRequired) 607{ 608 SL_ENTER_INTERFACE 609 610#if USE_PROFILES & (USE_PROFILES_GAME | USE_PROFILES_MUSIC) 611 if (NULL == pMetadataExtractor) { 612 result = SL_RESULT_PARAMETER_INVALID; 613 } else { 614 *pMetadataExtractor = NULL; 615 unsigned exposedMask; 616 const ClassTable *pCMetadataExtractor_class = 617 objectIDtoClass(SL_OBJECTID_METADATAEXTRACTOR); 618 if (NULL == pCMetadataExtractor_class) { 619 result = SL_RESULT_FEATURE_UNSUPPORTED; 620 } else { 621 result = checkInterfaces(pCMetadataExtractor_class, numInterfaces, 622 pInterfaceIds, pInterfaceRequired, &exposedMask); 623 } 624 if (SL_RESULT_SUCCESS == result) { 625 CMetadataExtractor *thiz = (CMetadataExtractor *) 626 construct(pCMetadataExtractor_class, exposedMask, self); 627 if (NULL == thiz) { 628 result = SL_RESULT_MEMORY_FAILURE; 629 } else { 630#if 0 631 "pDataSource", pDataSource, NONE, NONE 632#endif 633 IObject_Publish(&thiz->mObject); 634 // return the new metadata extractor object 635 *pMetadataExtractor = &thiz->mObject.mItf; 636 result = SL_RESULT_SUCCESS; 637 } 638 } 639 } 640#else 641 result = SL_RESULT_FEATURE_UNSUPPORTED; 642#endif 643 644 SL_LEAVE_INTERFACE 645} 646 647 648static SLresult IEngine_CreateExtensionObject(SLEngineItf self, SLObjectItf *pObject, 649 void *pParameters, SLuint32 objectID, SLuint32 numInterfaces, 650 const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired) 651{ 652 SL_ENTER_INTERFACE 653 654 if (NULL == pObject) { 655 result = SL_RESULT_PARAMETER_INVALID; 656 } else { 657 *pObject = NULL; 658 result = SL_RESULT_FEATURE_UNSUPPORTED; 659 } 660 661 SL_LEAVE_INTERFACE 662} 663 664 665static SLresult IEngine_QueryNumSupportedInterfaces(SLEngineItf self, 666 SLuint32 objectID, SLuint32 *pNumSupportedInterfaces) 667{ 668 SL_ENTER_INTERFACE 669 670 if (NULL == pNumSupportedInterfaces) { 671 result = SL_RESULT_PARAMETER_INVALID; 672 } else { 673 const ClassTable *clazz = objectIDtoClass(objectID); 674 if (NULL == clazz) { 675 result = SL_RESULT_FEATURE_UNSUPPORTED; 676 } else { 677 SLuint32 count = 0; 678 SLuint32 i; 679 for (i = 0; i < clazz->mInterfaceCount; ++i) { 680 switch (clazz->mInterfaces[i].mInterface) { 681 case INTERFACE_IMPLICIT: 682 case INTERFACE_IMPLICIT_PREREALIZE: 683 case INTERFACE_EXPLICIT: 684 case INTERFACE_EXPLICIT_PREREALIZE: 685 case INTERFACE_DYNAMIC: 686 ++count; 687 break; 688 case INTERFACE_UNAVAILABLE: 689 break; 690 default: 691 assert(false); 692 break; 693 } 694 } 695 *pNumSupportedInterfaces = count; 696 result = SL_RESULT_SUCCESS; 697 } 698 } 699 700 SL_LEAVE_INTERFACE; 701} 702 703 704static SLresult IEngine_QuerySupportedInterfaces(SLEngineItf self, 705 SLuint32 objectID, SLuint32 index, SLInterfaceID *pInterfaceId) 706{ 707 SL_ENTER_INTERFACE 708 709 if (NULL == pInterfaceId) { 710 result = SL_RESULT_PARAMETER_INVALID; 711 } else { 712 *pInterfaceId = NULL; 713 const ClassTable *clazz = objectIDtoClass(objectID); 714 if (NULL == clazz) { 715 result = SL_RESULT_FEATURE_UNSUPPORTED; 716 } else { 717 result = SL_RESULT_PARAMETER_INVALID; // will be reset later 718 SLuint32 i; 719 for (i = 0; i < clazz->mInterfaceCount; ++i) { 720 switch (clazz->mInterfaces[i].mInterface) { 721 case INTERFACE_IMPLICIT: 722 case INTERFACE_IMPLICIT_PREREALIZE: 723 case INTERFACE_EXPLICIT: 724 case INTERFACE_EXPLICIT_PREREALIZE: 725 case INTERFACE_DYNAMIC: 726 break; 727 case INTERFACE_UNAVAILABLE: 728 continue; 729 default: 730 assert(false); 731 break; 732 } 733 if (index == 0) { 734 *pInterfaceId = &SL_IID_array[clazz->mInterfaces[i].mMPH]; 735 result = SL_RESULT_SUCCESS; 736 break; 737 } 738 --index; 739 } 740 } 741 } 742 743 SL_LEAVE_INTERFACE 744}; 745 746 747static const char * const extensionNames[] = { 748#ifdef ANDROID 749 "ANDROID_SDK_LEVEL_12", // Android 3.0+ aka "Honeycomb MR1" 750#else 751 "WILHELM_DESKTOP", 752#endif 753}; 754 755 756static SLresult IEngine_QueryNumSupportedExtensions(SLEngineItf self, SLuint32 *pNumExtensions) 757{ 758 SL_ENTER_INTERFACE 759 760 if (NULL == pNumExtensions) { 761 result = SL_RESULT_PARAMETER_INVALID; 762 } else { 763 *pNumExtensions = sizeof(extensionNames) / sizeof(extensionNames[0]); 764 result = SL_RESULT_SUCCESS; 765 } 766 767 SL_LEAVE_INTERFACE 768} 769 770 771static SLresult IEngine_QuerySupportedExtension(SLEngineItf self, 772 SLuint32 index, SLchar *pExtensionName, SLint16 *pNameLength) 773{ 774 SL_ENTER_INTERFACE 775 776 if (NULL == pNameLength) { 777 result = SL_RESULT_PARAMETER_INVALID; 778 } else { 779 size_t actualNameLength; 780 unsigned numExtensions = sizeof(extensionNames) / sizeof(extensionNames[0]); 781 if (index >= numExtensions) { 782 actualNameLength = 0; 783 result = SL_RESULT_PARAMETER_INVALID; 784 } else { 785 const char *extensionName = extensionNames[index]; 786 actualNameLength = strlen(extensionName) + 1; 787 if (NULL == pExtensionName) { 788 // application is querying the name length in order to allocate a buffer 789 result = SL_RESULT_SUCCESS; 790 } else { 791 SLint16 availableNameLength = *pNameLength; 792 if (0 >= availableNameLength) { 793 // there is not even room for the terminating NUL 794 result = SL_RESULT_BUFFER_INSUFFICIENT; 795 } else if (actualNameLength > (size_t) availableNameLength) { 796 // "no invalid strings are written. That is, the null-terminator always exists" 797 memcpy(pExtensionName, extensionName, (size_t) availableNameLength - 1); 798 pExtensionName[(size_t) availableNameLength - 1] = '\0'; 799 result = SL_RESULT_BUFFER_INSUFFICIENT; 800 } else { 801 memcpy(pExtensionName, extensionName, actualNameLength); 802 result = SL_RESULT_SUCCESS; 803 } 804 } 805 } 806 *pNameLength = actualNameLength; 807 } 808 809 SL_LEAVE_INTERFACE 810} 811 812 813static SLresult IEngine_IsExtensionSupported(SLEngineItf self, 814 const SLchar *pExtensionName, SLboolean *pSupported) 815{ 816 SL_ENTER_INTERFACE 817 818 if (NULL == pSupported) { 819 result = SL_RESULT_PARAMETER_INVALID; 820 } else { 821 SLboolean isSupported = SL_BOOLEAN_FALSE; 822 if (NULL == pExtensionName) { 823 result = SL_RESULT_PARAMETER_INVALID; 824 } else { 825 unsigned numExtensions = sizeof(extensionNames) / sizeof(extensionNames[0]); 826 unsigned i; 827 for (i = 0; i < numExtensions; ++i) { 828 if (!strcmp((const char *) pExtensionName, extensionNames[i])) { 829 isSupported = SL_BOOLEAN_TRUE; 830 break; 831 } 832 } 833 result = SL_RESULT_SUCCESS; 834 } 835 *pSupported = isSupported; 836 } 837 838 SL_LEAVE_INTERFACE 839} 840 841 842static const struct SLEngineItf_ IEngine_Itf = { 843 IEngine_CreateLEDDevice, 844 IEngine_CreateVibraDevice, 845 IEngine_CreateAudioPlayer, 846 IEngine_CreateAudioRecorder, 847 IEngine_CreateMidiPlayer, 848 IEngine_CreateListener, 849 IEngine_Create3DGroup, 850 IEngine_CreateOutputMix, 851 IEngine_CreateMetadataExtractor, 852 IEngine_CreateExtensionObject, 853 IEngine_QueryNumSupportedInterfaces, 854 IEngine_QuerySupportedInterfaces, 855 IEngine_QueryNumSupportedExtensions, 856 IEngine_QuerySupportedExtension, 857 IEngine_IsExtensionSupported 858}; 859 860void IEngine_init(void *self) 861{ 862 IEngine *thiz = (IEngine *) self; 863 thiz->mItf = &IEngine_Itf; 864 // mLossOfControlGlobal is initialized in slCreateEngine 865#ifdef USE_SDL 866 thiz->mOutputMix = NULL; 867#endif 868 thiz->mInstanceCount = 1; // ourself 869 thiz->mInstanceMask = 0; 870 thiz->mChangedMask = 0; 871 unsigned i; 872 for (i = 0; i < MAX_INSTANCE; ++i) { 873 thiz->mInstances[i] = NULL; 874 } 875 thiz->mShutdown = SL_BOOLEAN_FALSE; 876 thiz->mShutdownAck = SL_BOOLEAN_FALSE; 877} 878 879void IEngine_deinit(void *self) 880{ 881} 882 883 884// OpenMAX AL Engine 885 886 887static XAresult IEngine_CreateCameraDevice(XAEngineItf self, XAObjectItf *pDevice, 888 XAuint32 deviceID, XAuint32 numInterfaces, const XAInterfaceID *pInterfaceIds, 889 const XAboolean *pInterfaceRequired) 890{ 891 XA_ENTER_INTERFACE 892 893 //IXAEngine *thiz = (IXAEngine *) self; 894 result = SL_RESULT_FEATURE_UNSUPPORTED; 895 896 XA_LEAVE_INTERFACE 897} 898 899 900static XAresult IEngine_CreateRadioDevice(XAEngineItf self, XAObjectItf *pDevice, 901 XAuint32 numInterfaces, const XAInterfaceID *pInterfaceIds, 902 const XAboolean *pInterfaceRequired) 903{ 904 XA_ENTER_INTERFACE 905 906 //IXAEngine *thiz = (IXAEngine *) self; 907 result = SL_RESULT_FEATURE_UNSUPPORTED; 908 909 XA_LEAVE_INTERFACE 910} 911 912 913static XAresult IXAEngine_CreateLEDDevice(XAEngineItf self, XAObjectItf *pDevice, XAuint32 deviceID, 914 XAuint32 numInterfaces, const XAInterfaceID *pInterfaceIds, 915 const XAboolean *pInterfaceRequired) 916{ 917 // forward to OpenSL ES 918 return IEngine_CreateLEDDevice(&((CEngine *) ((IXAEngine *) self)->mThis)->mEngine.mItf, 919 (SLObjectItf *) pDevice, deviceID, numInterfaces, (const SLInterfaceID *) pInterfaceIds, 920 (const SLboolean *) pInterfaceRequired); 921} 922 923 924static XAresult IXAEngine_CreateVibraDevice(XAEngineItf self, XAObjectItf *pDevice, 925 XAuint32 deviceID, XAuint32 numInterfaces, const XAInterfaceID *pInterfaceIds, 926 const XAboolean *pInterfaceRequired) 927{ 928 // forward to OpenSL ES 929 return IEngine_CreateVibraDevice(&((CEngine *) ((IXAEngine *) self)->mThis)->mEngine.mItf, 930 (SLObjectItf *) pDevice, deviceID, numInterfaces, (const SLInterfaceID *) pInterfaceIds, 931 (const SLboolean *) pInterfaceRequired); 932} 933 934 935static XAresult IEngine_CreateMediaPlayer(XAEngineItf self, XAObjectItf *pPlayer, 936 XADataSource *pDataSrc, XADataSource *pBankSrc, XADataSink *pAudioSnk, 937 XADataSink *pImageVideoSnk, XADataSink *pVibra, XADataSink *pLEDArray, 938 XAuint32 numInterfaces, const XAInterfaceID *pInterfaceIds, 939 const XAboolean *pInterfaceRequired) 940{ 941 XA_ENTER_INTERFACE 942 943 if (NULL == pPlayer) { 944 result = XA_RESULT_PARAMETER_INVALID; 945 } else { 946 *pPlayer = NULL; 947 unsigned exposedMask; 948 const ClassTable *pCMediaPlayer_class = objectIDtoClass(XA_OBJECTID_MEDIAPLAYER); 949 assert(NULL != pCMediaPlayer_class); 950 result = checkInterfaces(pCMediaPlayer_class, numInterfaces, 951 (const SLInterfaceID *) pInterfaceIds, pInterfaceRequired, &exposedMask); 952 if (XA_RESULT_SUCCESS == result) { 953 954 // Construct our new MediaPlayer instance 955 CMediaPlayer *thiz = (CMediaPlayer *) construct(pCMediaPlayer_class, exposedMask, 956 &((CEngine *) ((IXAEngine *) self)->mThis)->mEngine.mItf); 957 if (NULL == thiz) { 958 result = XA_RESULT_MEMORY_FAILURE; 959 } else { 960 961 do { 962 963 // Initialize private fields not associated with an interface 964 965 // (assume calloc or memset 0 during allocation) 966 // placement new 967 968 969 // Check the source and sink parameters against generic constraints 970 971 result = checkDataSource("pDataSrc", (const SLDataSource *) pDataSrc, 972 &thiz->mDataSource, DATALOCATOR_MASK_URI 973#ifdef ANDROID 974 | DATALOCATOR_MASK_ANDROIDFD 975 | DATALOCATOR_MASK_ANDROIDBUFFERQUEUE 976#endif 977 , DATAFORMAT_MASK_MIME); 978 if (XA_RESULT_SUCCESS != result) { 979 break; 980 } 981 982 result = checkDataSource("pBankSrc", (const SLDataSource *) pBankSrc, 983 &thiz->mBankSource, DATALOCATOR_MASK_NULL | DATALOCATOR_MASK_URI | 984 DATALOCATOR_MASK_ADDRESS, DATAFORMAT_MASK_NULL); 985 if (XA_RESULT_SUCCESS != result) { 986 break; 987 } 988 989 result = checkDataSink("pAudioSnk", (const SLDataSink *) pAudioSnk, 990 &thiz->mAudioSink, DATALOCATOR_MASK_OUTPUTMIX, DATAFORMAT_MASK_NULL); 991 if (XA_RESULT_SUCCESS != result) { 992 break; 993 } 994 995 result = checkDataSink("pImageVideoSnk", (const SLDataSink *) pImageVideoSnk, 996 &thiz->mImageVideoSink, DATALOCATOR_MASK_NATIVEDISPLAY, 997 DATAFORMAT_MASK_NULL); 998 if (XA_RESULT_SUCCESS != result) { 999 break; 1000 } 1001 1002 result = checkDataSink("pVibra", (const SLDataSink *) pVibra, &thiz->mVibraSink, 1003 DATALOCATOR_MASK_NULL | DATALOCATOR_MASK_IODEVICE, 1004 DATAFORMAT_MASK_NULL); 1005 if (XA_RESULT_SUCCESS != result) { 1006 break; 1007 } 1008 1009 result = checkDataSink("pLEDArray", (const SLDataSink *) pLEDArray, 1010 &thiz->mLEDArraySink, DATALOCATOR_MASK_NULL | DATALOCATOR_MASK_IODEVICE, 1011 DATAFORMAT_MASK_NULL); 1012 if (XA_RESULT_SUCCESS != result) { 1013 break; 1014 } 1015 1016 // Unsafe to ever refer to application pointers again 1017 pDataSrc = NULL; 1018 pBankSrc = NULL; 1019 pAudioSnk = NULL; 1020 pImageVideoSnk = NULL; 1021 pVibra = NULL; 1022 pLEDArray = NULL; 1023 1024 // Check that the requested interfaces are compatible with the data source 1025 // ... 1026 1027 // check the source and sink parameters against platform support 1028#ifdef ANDROID 1029 // result = android_mediaPlayer_checkSourceSink(thiz); 1030 if (XA_RESULT_SUCCESS != result) { 1031 break; 1032 } 1033#endif 1034 1035 // platform-specific initialization 1036#ifdef ANDROID 1037 android_Player_create(thiz); 1038#endif 1039 1040 } while (0); 1041 1042 if (XA_RESULT_SUCCESS != result) { 1043 IObject_Destroy(&thiz->mObject.mItf); 1044 } else { 1045 IObject_Publish(&thiz->mObject); 1046 // return the new media player object 1047 *pPlayer = (XAObjectItf) &thiz->mObject.mItf; 1048 } 1049 1050 } 1051 } 1052 1053 } 1054 1055 XA_LEAVE_INTERFACE 1056} 1057 1058 1059static XAresult IEngine_CreateMediaRecorder(XAEngineItf self, XAObjectItf *pRecorder, 1060 XADataSource *pAudioSrc, XADataSource *pImageVideoSrc, 1061 XADataSink *pDataSnk, XAuint32 numInterfaces, const XAInterfaceID *pInterfaceIds, 1062 const XAboolean *pInterfaceRequired) 1063{ 1064 XA_ENTER_INTERFACE 1065 1066 //IXAEngine *thiz = (IXAEngine *) self; 1067 result = SL_RESULT_FEATURE_UNSUPPORTED; 1068 1069#if 0 1070 "pAudioSrc", pAudioSrc, 1071 "pImageVideoSrc", pImageVideoSrc, 1072 "pDataSink", pDataSnk, 1073#endif 1074 1075 XA_LEAVE_INTERFACE 1076} 1077 1078 1079static XAresult IXAEngine_CreateOutputMix(XAEngineItf self, XAObjectItf *pMix, 1080 XAuint32 numInterfaces, const XAInterfaceID *pInterfaceIds, 1081 const XAboolean *pInterfaceRequired) 1082{ 1083 // forward to OpenSL ES 1084 return IEngine_CreateOutputMix(&((CEngine *) ((IXAEngine *) self)->mThis)->mEngine.mItf, 1085 (SLObjectItf *) pMix, numInterfaces, (const SLInterfaceID *) pInterfaceIds, 1086 (const SLboolean *) pInterfaceRequired); 1087} 1088 1089 1090static XAresult IXAEngine_CreateMetadataExtractor(XAEngineItf self, XAObjectItf *pMetadataExtractor, 1091 XADataSource *pDataSource, XAuint32 numInterfaces, 1092 const XAInterfaceID *pInterfaceIds, const XAboolean *pInterfaceRequired) 1093{ 1094 // forward to OpenSL ES 1095 return IEngine_CreateMetadataExtractor(&((CEngine *) ((IXAEngine *) self)->mThis)->mEngine.mItf, 1096 (SLObjectItf *) pMetadataExtractor, (SLDataSource *) pDataSource, numInterfaces, 1097 (const SLInterfaceID *) pInterfaceIds, (const SLboolean *) pInterfaceRequired); 1098} 1099 1100 1101static XAresult IXAEngine_CreateExtensionObject(XAEngineItf self, XAObjectItf *pObject, 1102 void *pParameters, XAuint32 objectID, XAuint32 numInterfaces, 1103 const XAInterfaceID *pInterfaceIds, const XAboolean *pInterfaceRequired) 1104{ 1105 // forward to OpenSL ES 1106 return IEngine_CreateExtensionObject(&((CEngine *) ((IXAEngine *) self)->mThis)->mEngine.mItf, 1107 (SLObjectItf *) pObject, pParameters, objectID, numInterfaces, 1108 (const SLInterfaceID *) pInterfaceIds, (const SLboolean *) pInterfaceRequired); 1109} 1110 1111 1112static XAresult IEngine_GetImplementationInfo(XAEngineItf self, XAuint32 *pMajor, XAuint32 *pMinor, 1113 XAuint32 *pStep, /* XAuint32 nImplementationTextSize, */ const XAchar *pImplementationText) 1114{ 1115 XA_ENTER_INTERFACE 1116 1117 //IXAEngine *thiz = (IXAEngine *) self; 1118 result = SL_RESULT_FEATURE_UNSUPPORTED; 1119 1120 XA_LEAVE_INTERFACE 1121} 1122 1123 1124static XAresult IXAEngine_QuerySupportedProfiles(XAEngineItf self, XAint16 *pProfilesSupported) 1125{ 1126 XA_ENTER_INTERFACE 1127 1128 if (NULL == pProfilesSupported) { 1129 result = XA_RESULT_PARAMETER_INVALID; 1130 } else { 1131#if 1 1132 *pProfilesSupported = 0; 1133 // the code below was copied from OpenSL ES and needs to be adapted for OpenMAX AL. 1134#else 1135 // The generic implementation doesn't implement any of the profiles, they shouldn't be 1136 // declared as supported. Also exclude the fake profiles BASE and OPTIONAL. 1137 *pProfilesSupported = USE_PROFILES & 1138 (USE_PROFILES_GAME | USE_PROFILES_MUSIC | USE_PROFILES_PHONE); 1139#endif 1140 result = XA_RESULT_SUCCESS; 1141 } 1142 1143 XA_LEAVE_INTERFACE 1144} 1145 1146 1147static XAresult IXAEngine_QueryNumSupportedInterfaces(XAEngineItf self, XAuint32 objectID, 1148 XAuint32 *pNumSupportedInterfaces) 1149{ 1150 // forward to OpenSL ES 1151 return IEngine_QueryNumSupportedInterfaces( 1152 &((CEngine *) ((IXAEngine *) self)->mThis)->mEngine.mItf, objectID, 1153 pNumSupportedInterfaces); 1154} 1155 1156 1157static XAresult IXAEngine_QuerySupportedInterfaces(XAEngineItf self, XAuint32 objectID, 1158 XAuint32 index, XAInterfaceID *pInterfaceId) 1159{ 1160 // forward to OpenSL ES 1161 return IEngine_QuerySupportedInterfaces( 1162 &((CEngine *) ((IXAEngine *) self)->mThis)->mEngine.mItf, objectID, index, 1163 (SLInterfaceID *) pInterfaceId); 1164} 1165 1166 1167static XAresult IXAEngine_QueryNumSupportedExtensions(XAEngineItf self, XAuint32 *pNumExtensions) 1168{ 1169 // forward to OpenSL ES 1170 return IEngine_QueryNumSupportedExtensions( 1171 &((CEngine *) ((IXAEngine *) self)->mThis)->mEngine.mItf, pNumExtensions); 1172} 1173 1174 1175static XAresult IXAEngine_QuerySupportedExtension(XAEngineItf self, XAuint32 index, 1176 XAchar *pExtensionName, XAint16 *pNameLength) 1177{ 1178 // forward to OpenSL ES 1179 return IEngine_QuerySupportedExtension(&((CEngine *) ((IXAEngine *) self)->mThis)->mEngine.mItf, 1180 index, pExtensionName, (SLint16 *) pNameLength); 1181} 1182 1183 1184static XAresult IXAEngine_IsExtensionSupported(XAEngineItf self, const XAchar *pExtensionName, 1185 XAboolean *pSupported) 1186{ 1187 // forward to OpenSL ES 1188 return IEngine_IsExtensionSupported(&((CEngine *) ((IXAEngine *) self)->mThis)->mEngine.mItf, 1189 pExtensionName, pSupported); 1190} 1191 1192 1193static XAresult IXAEngine_QueryLEDCapabilities(XAEngineItf self, XAuint32 *pIndex, 1194 XAuint32 *pLEDDeviceID, XALEDDescriptor *pDescriptor) 1195{ 1196 // forward to OpenSL ES EngineCapabilities 1197 return (XAresult) IEngineCapabilities_QueryLEDCapabilities( 1198 &((CEngine *) ((IXAEngine *) self)->mThis)->mEngineCapabilities.mItf, pIndex, 1199 pLEDDeviceID, (SLLEDDescriptor *) pDescriptor); 1200} 1201 1202 1203static XAresult IXAEngine_QueryVibraCapabilities(XAEngineItf self, XAuint32 *pIndex, 1204 XAuint32 *pVibraDeviceID, XAVibraDescriptor *pDescriptor) 1205{ 1206 // forward to OpenSL ES EngineCapabilities 1207 return (XAresult) IEngineCapabilities_QueryVibraCapabilities( 1208 &((CEngine *) ((IXAEngine *) self)->mThis)->mEngineCapabilities.mItf, pIndex, 1209 pVibraDeviceID, (SLVibraDescriptor *) pDescriptor); 1210} 1211 1212 1213// OpenMAX AL engine v-table 1214 1215static const struct XAEngineItf_ IXAEngine_Itf = { 1216 IEngine_CreateCameraDevice, 1217 IEngine_CreateRadioDevice, 1218 IXAEngine_CreateLEDDevice, 1219 IXAEngine_CreateVibraDevice, 1220 IEngine_CreateMediaPlayer, 1221 IEngine_CreateMediaRecorder, 1222 IXAEngine_CreateOutputMix, 1223 IXAEngine_CreateMetadataExtractor, 1224 IXAEngine_CreateExtensionObject, 1225 IEngine_GetImplementationInfo, 1226 IXAEngine_QuerySupportedProfiles, 1227 IXAEngine_QueryNumSupportedInterfaces, 1228 IXAEngine_QuerySupportedInterfaces, 1229 IXAEngine_QueryNumSupportedExtensions, 1230 IXAEngine_QuerySupportedExtension, 1231 IXAEngine_IsExtensionSupported, 1232 IXAEngine_QueryLEDCapabilities, 1233 IXAEngine_QueryVibraCapabilities 1234}; 1235 1236 1237void IXAEngine_init(void *self) 1238{ 1239 IXAEngine *thiz = (IXAEngine *) self; 1240 thiz->mItf = &IXAEngine_Itf; 1241} 1242