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