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