sles.c revision a3080daa505f91df51a808c85ddb37c48745bf7c
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/* OpenSL ES private and global functions not associated with an interface or class */ 18 19#include "sles_allinclusive.h" 20 21 22/** \brief Return true if the specified interface exists and has been initialized for this object. 23 * Returns false if the class does not support this kind of interface, or the class supports the 24 * interface but this particular object has not had the interface exposed at object creation time 25 * or by DynamicInterface::AddInterface. Note that the return value is not affected by whether 26 * the application has requested access to the interface with Object::GetInterface. Assumes on 27 * entry that the object is locked for either shared or exclusive access. 28 */ 29 30bool IsInterfaceInitialized(IObject *this, unsigned MPH) 31{ 32 assert(NULL != this); 33 assert( /* (MPH_MIN <= MPH) && */ (MPH < (unsigned) MPH_MAX)); 34 const ClassTable *class__ = this->mClass; 35 assert(NULL != class__); 36 int index; 37 if (0 > (index = class__->mMPH_to_index[MPH])) { 38 return false; 39 } 40 assert(MAX_INDEX >= class__->mInterfaceCount); 41 assert(class__->mInterfaceCount > (unsigned) index); 42 switch (this->mInterfaceStates[index]) { 43 case INTERFACE_EXPOSED: 44 case INTERFACE_ADDED: 45 return true; 46 default: 47 return false; 48 } 49} 50 51 52/** \brief Map an IObject to it's "object ID" (which is really a class ID) */ 53 54SLuint32 IObjectToObjectID(IObject *this) 55{ 56 assert(NULL != this); 57 return this->mClass->mObjectID; 58} 59 60 61/** \brief Acquire a strong reference to an object. 62 * Check that object has the specified "object ID" (which is really a class ID) and is in the 63 * realized state. If so, then acquire a strong reference to it and return true. 64 * Otherwise return false. 65 */ 66 67SLresult AcquireStrongRef(IObject *object, SLuint32 expectedObjectID) 68{ 69 if (NULL == object) { 70 return SL_RESULT_PARAMETER_INVALID; 71 } 72 // NTH additional validity checks on address here 73 SLresult result; 74 object_lock_exclusive(object); 75 SLuint32 actualObjectID = IObjectToObjectID(object); 76 if (expectedObjectID != actualObjectID) { 77 SL_LOGE("object %p has object ID %lu but expected %lu", object, actualObjectID, 78 expectedObjectID); 79 result = SL_RESULT_PARAMETER_INVALID; 80 } else if (SL_OBJECT_STATE_REALIZED != object->mState) { 81 SL_LOGE("object %p with object ID %lu is not realized", object, actualObjectID); 82 result = SL_RESULT_PRECONDITIONS_VIOLATED; 83 } else { 84 ++object->mStrongRefCount; 85 result = SL_RESULT_SUCCESS; 86 } 87 object_unlock_exclusive(object); 88 return result; 89} 90 91 92/** \brief Release a strong reference to an object. 93 * Entry condition: the object is locked. 94 * Exit condition: the object is unlocked. 95 * Finishes the destroy if needed. 96 */ 97 98void ReleaseStrongRefAndUnlockExclusive(IObject *object) 99{ 100#ifdef USE_DEBUG 101 assert(pthread_equal(pthread_self(), object->mOwner)); 102#endif 103 assert(0 < object->mStrongRefCount); 104 if ((0 == --object->mStrongRefCount) && (SL_OBJECT_STATE_DESTROYING == object->mState)) { 105 // FIXME do the destroy here - merge with IDestroy 106 // but can't do this until we move Destroy to the sync thread 107 // as Destroy is now a blocking operation, and to avoid a race 108 } else { 109 object_unlock_exclusive(object); 110 } 111} 112 113 114/** \brief Release a strong reference to an object. 115 * Entry condition: the object is unlocked. 116 * Exit condition: the object is unlocked. 117 * Finishes the destroy if needed. 118 */ 119 120void ReleaseStrongRef(IObject *object) 121{ 122 assert(NULL != object); 123 object_lock_exclusive(object); 124 ReleaseStrongRefAndUnlockExclusive(object); 125} 126 127 128/** \brief Convert POSIX pthread error code to OpenSL ES result code */ 129 130SLresult err_to_result(int err) 131{ 132 if (EAGAIN == err || ENOMEM == err) { 133 return SL_RESULT_RESOURCE_ERROR; 134 } 135 if (0 != err) { 136 return SL_RESULT_INTERNAL_ERROR; 137 } 138 return SL_RESULT_SUCCESS; 139} 140 141 142/** \brief Check the interface IDs passed into a Create operation */ 143 144SLresult checkInterfaces(const ClassTable *class__, SLuint32 numInterfaces, 145 const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired, unsigned *pExposedMask) 146{ 147 assert(NULL != class__ && NULL != pExposedMask); 148 // Initially no interfaces are exposed 149 unsigned exposedMask = 0; 150 const struct iid_vtable *interfaces = class__->mInterfaces; 151 SLuint32 interfaceCount = class__->mInterfaceCount; 152 SLuint32 i; 153 // Expose all implicit interfaces 154 for (i = 0; i < interfaceCount; ++i) { 155 switch (interfaces[i].mInterface) { 156 case INTERFACE_IMPLICIT: 157 // there must be an initialization hook present 158 if (NULL != MPH_init_table[interfaces[i].mMPH].mInit) { 159 exposedMask |= 1 << i; 160 } 161 break; 162 default: 163 break; 164 } 165 } 166 if (0 < numInterfaces) { 167 if (NULL == pInterfaceIds || NULL == pInterfaceRequired) { 168 return SL_RESULT_PARAMETER_INVALID; 169 } 170 // Loop for each requested interface 171 for (i = 0; i < numInterfaces; ++i) { 172 SLInterfaceID iid = pInterfaceIds[i]; 173 if (NULL == iid) { 174 return SL_RESULT_PARAMETER_INVALID; 175 } 176 int MPH, index; 177 if ((0 > (MPH = IID_to_MPH(iid))) || 178 // there must be an initialization hook present 179 (NULL == MPH_init_table[MPH].mInit) || 180 (0 > (index = class__->mMPH_to_index[MPH]))) { 181 // Here if interface was not found, or is not available for this object type 182 if (pInterfaceRequired[i]) { 183 // Application said it required the interface, so give up 184 SL_LOGE("class %s interface %lu required but unavailable MPH=%d", 185 class__->mName, i, MPH); 186 return SL_RESULT_FEATURE_UNSUPPORTED; 187 } 188 // Application said it didn't really need the interface, so ignore 189 continue; 190 } 191 // The requested interface was both found and available, so expose it 192 exposedMask |= (1 << index); 193 // Note that we ignore duplicate requests, including equal and aliased IDs 194 } 195 } 196 *pExposedMask = exposedMask; 197 return SL_RESULT_SUCCESS; 198} 199 200 201/** \brief Helper shared by decoder and encoder */ 202 203SLresult GetCodecCapabilities(SLuint32 codecId, SLuint32 *pIndex, 204 SLAudioCodecDescriptor *pDescriptor, const CodecDescriptor *codecDescriptors) 205{ 206 if (NULL == pIndex) { 207 return SL_RESULT_PARAMETER_INVALID; 208 } 209 const CodecDescriptor *cd = codecDescriptors; 210 SLuint32 index; 211 if (NULL == pDescriptor) { 212 for (index = 0 ; NULL != cd->mDescriptor; ++cd) { 213 if (cd->mCodecID == codecId) { 214 ++index; 215 } 216 } 217 *pIndex = index; 218 return SL_RESULT_SUCCESS; 219 } 220 index = *pIndex; 221 for ( ; NULL != cd->mDescriptor; ++cd) { 222 if (cd->mCodecID == codecId) { 223 if (0 == index) { 224 *pDescriptor = *cd->mDescriptor; 225#if 0 // Temporary workaround for Khronos bug 6331 226 if (0 < pDescriptor->numSampleRatesSupported) { 227 // The malloc is not in the 1.0.1 specification 228 SLmilliHertz *temp = (SLmilliHertz *) malloc(sizeof(SLmilliHertz) * 229 pDescriptor->numSampleRatesSupported); 230 assert(NULL != temp); 231 memcpy(temp, pDescriptor->pSampleRatesSupported, sizeof(SLmilliHertz) * 232 pDescriptor->numSampleRatesSupported); 233 pDescriptor->pSampleRatesSupported = temp; 234 } else { 235 pDescriptor->pSampleRatesSupported = NULL; 236 } 237#endif 238 return SL_RESULT_SUCCESS; 239 } 240 --index; 241 } 242 } 243 return SL_RESULT_PARAMETER_INVALID; 244} 245 246 247/** \brief Check a data locator and make local deep copy */ 248 249static SLresult checkDataLocator(void *pLocator, DataLocator *pDataLocator) 250{ 251 if (NULL == pLocator) { 252 pDataLocator->mLocatorType = SL_DATALOCATOR_NULL; 253 return SL_RESULT_SUCCESS; 254 } 255 SLresult result; 256 SLuint32 locatorType = *(SLuint32 *)pLocator; 257 switch (locatorType) { 258 259 case SL_DATALOCATOR_ADDRESS: 260 pDataLocator->mAddress = *(SLDataLocator_Address *)pLocator; 261 // if length is greater than zero, then the address must be non-NULL 262 if ((0 < pDataLocator->mAddress.length) && (NULL == pDataLocator->mAddress.pAddress)) { 263 SL_LOGE("pAddress is NULL"); 264 return SL_RESULT_PARAMETER_INVALID; 265 } 266 break; 267 268 case SL_DATALOCATOR_BUFFERQUEUE: 269#ifdef ANDROID 270 // This is an alias that is _not_ converted; the rest of the code must check for both locator 271 // types. That's because it is only an alias for audio players, not audio recorder objects 272 // so we have to remember the distinction. 273 case SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE: 274#endif 275 pDataLocator->mBufferQueue = *(SLDataLocator_BufferQueue *)pLocator; 276 // number of buffers must be specified, there is no default value, and must not be excessive 277 if (!((1 <= pDataLocator->mBufferQueue.numBuffers) && 278 (pDataLocator->mBufferQueue.numBuffers <= 255))) { 279 SL_LOGE("numBuffers=%u", (unsigned) pDataLocator->mBufferQueue.numBuffers); 280 return SL_RESULT_PARAMETER_INVALID; 281 } 282 break; 283 284 case SL_DATALOCATOR_IODEVICE: 285 { 286 pDataLocator->mIODevice = *(SLDataLocator_IODevice *)pLocator; 287 SLuint32 deviceType = pDataLocator->mIODevice.deviceType; 288 SLObjectItf device = pDataLocator->mIODevice.device; 289 if (NULL != device) { 290 pDataLocator->mIODevice.deviceID = 0; 291 SLuint32 expectedObjectID; 292 switch (deviceType) { 293 case SL_IODEVICE_LEDARRAY: 294 expectedObjectID = SL_OBJECTID_LEDDEVICE; 295 break; 296 case SL_IODEVICE_VIBRA: 297 expectedObjectID = SL_OBJECTID_VIBRADEVICE; 298 break; 299 // audio input and audio output cannot be specified via objects 300 case SL_IODEVICE_AUDIOINPUT: 301 // worse yet, an SL_IODEVICE enum constant for audio output does not exist yet 302 // case SL_IODEVICE_AUDIOOUTPUT: 303 default: 304 SL_LOGE("invalid deviceType %lu", deviceType); 305 pDataLocator->mIODevice.device = NULL; 306 return SL_RESULT_PARAMETER_INVALID; 307 } 308 // check that device has the correct object ID and is realized, 309 // and acquire a strong reference to it 310 result = AcquireStrongRef((IObject *) device, expectedObjectID); 311 if (SL_RESULT_SUCCESS != result) { 312 SL_LOGE("locator type is IODEVICE, but device field %p has wrong object ID or is " \ 313 "not realized", device); 314 pDataLocator->mIODevice.device = NULL; 315 return result; 316 } 317 } else { 318 SLuint32 deviceID = pDataLocator->mIODevice.deviceID; 319 // FIXME this section should be OEM-configurable 320 switch (deviceType) { 321 case SL_IODEVICE_LEDARRAY: 322 if (SL_DEFAULTDEVICEID_LED != deviceID) { 323 SL_LOGE("invalid LED deviceID %lu", deviceID); 324 return SL_RESULT_PARAMETER_INVALID; 325 } 326 break; 327 case SL_IODEVICE_VIBRA: 328 if (SL_DEFAULTDEVICEID_VIBRA != deviceID) { 329 SL_LOGE("invalid vibra deviceID %lu", deviceID); 330 return SL_RESULT_PARAMETER_INVALID; 331 } 332 break; 333 case SL_IODEVICE_AUDIOINPUT: 334 if (SL_DEFAULTDEVICEID_AUDIOINPUT != deviceID) { 335 SL_LOGE("invalid audio input deviceID %lu", deviceID); 336 return SL_RESULT_PARAMETER_INVALID; 337 } 338 break; 339 default: 340 SL_LOGE("invalid deviceType %lu", deviceType); 341 return SL_RESULT_PARAMETER_INVALID; 342 } 343 } 344 } 345 break; 346 347 case SL_DATALOCATOR_MIDIBUFFERQUEUE: 348 pDataLocator->mMIDIBufferQueue = *(SLDataLocator_MIDIBufferQueue *)pLocator; 349 if (0 == pDataLocator->mMIDIBufferQueue.tpqn) { 350 pDataLocator->mMIDIBufferQueue.tpqn = 192; 351 } 352 // number of buffers must be specified, there is no default value, and must not be excessive 353 if (!((1 <= pDataLocator->mMIDIBufferQueue.numBuffers) && 354 (pDataLocator->mMIDIBufferQueue.numBuffers <= 255))) { 355 SL_LOGE("invalid MIDI buffer queue"); 356 return SL_RESULT_PARAMETER_INVALID; 357 } 358 break; 359 360 case SL_DATALOCATOR_OUTPUTMIX: 361 pDataLocator->mOutputMix = *(SLDataLocator_OutputMix *)pLocator; 362 // check that output mix object has the correct object ID and is realized, 363 // and acquire a strong reference to it 364 result = AcquireStrongRef((IObject *) pDataLocator->mOutputMix.outputMix, 365 SL_OBJECTID_OUTPUTMIX); 366 if (SL_RESULT_SUCCESS != result) { 367 SL_LOGE("locatorType is SL_DATALOCATOR_OUTPUTMIX, but outputMix field %p does not " \ 368 "refer to an SL_OBJECTID_OUTPUTMIX or is not realized", \ 369 pDataLocator->mOutputMix.outputMix); 370 pDataLocator->mOutputMix.outputMix = NULL; 371 return result; 372 } 373 break; 374 375 case SL_DATALOCATOR_URI: 376 { 377 pDataLocator->mURI = *(SLDataLocator_URI *)pLocator; 378 if (NULL == pDataLocator->mURI.URI) { 379 SL_LOGE("invalid URI"); 380 return SL_RESULT_PARAMETER_INVALID; 381 } 382 // NTH verify URI address for validity 383 size_t len = strlen((const char *) pDataLocator->mURI.URI); 384 SLchar *myURI = (SLchar *) malloc(len + 1); 385 if (NULL == myURI) { 386 pDataLocator->mURI.URI = NULL; 387 return SL_RESULT_MEMORY_FAILURE; 388 } 389 memcpy(myURI, pDataLocator->mURI.URI, len + 1); 390 // Verify that another thread didn't change the NUL-terminator after we used it 391 // to determine length of string to copy. It's OK if the string became shorter. 392 if ('\0' != myURI[len]) { 393 free(myURI); 394 pDataLocator->mURI.URI = NULL; 395 return SL_RESULT_PARAMETER_INVALID; 396 } 397 pDataLocator->mURI.URI = myURI; 398 } 399 break; 400 401#ifdef ANDROID 402 case SL_DATALOCATOR_ANDROIDFD: 403 { 404 pDataLocator->mFD = *(SLDataLocator_AndroidFD *)pLocator; 405 SL_LOGV("Data locator FD: fd=%ld offset=%lld length=%lld", pDataLocator->mFD.fd, 406 pDataLocator->mFD.offset, pDataLocator->mFD.length); 407 // NTH check against process fd limit 408 if (0 > pDataLocator->mFD.fd) { 409 return SL_RESULT_PARAMETER_INVALID; 410 } 411 } 412 break; 413#endif 414 415 default: 416 SL_LOGE("invalid locatorType %lu", locatorType); 417 return SL_RESULT_PARAMETER_INVALID; 418 } 419 420 // Verify that another thread didn't change the locatorType field after we used it 421 // to determine sizeof struct to copy. 422 if (locatorType != pDataLocator->mLocatorType) { 423 return SL_RESULT_PARAMETER_INVALID; 424 } 425 return SL_RESULT_SUCCESS; 426} 427 428 429/** \brief Free the local deep copy of a data locator */ 430 431static void freeDataLocator(DataLocator *pDataLocator) 432{ 433 switch (pDataLocator->mLocatorType) { 434 case SL_DATALOCATOR_URI: 435 if (NULL != pDataLocator->mURI.URI) { 436 free(pDataLocator->mURI.URI); 437 pDataLocator->mURI.URI = NULL; 438 } 439 pDataLocator->mURI.URI = NULL; 440 break; 441 case SL_DATALOCATOR_IODEVICE: 442 if (NULL != pDataLocator->mIODevice.device) { 443 ReleaseStrongRef((IObject *) pDataLocator->mIODevice.device); 444 pDataLocator->mIODevice.device = NULL; 445 } 446 break; 447 case SL_DATALOCATOR_OUTPUTMIX: 448 if (NULL != pDataLocator->mOutputMix.outputMix) { 449 ReleaseStrongRef((IObject *) pDataLocator->mOutputMix.outputMix); 450 pDataLocator->mOutputMix.outputMix = NULL; 451 } 452 break; 453 default: 454 break; 455 } 456} 457 458 459/** \brief Check a data format and make local deep copy */ 460 461static SLresult checkDataFormat(void *pFormat, DataFormat *pDataFormat) 462{ 463 SLresult result = SL_RESULT_SUCCESS; 464 465 if (NULL == pFormat) { 466 pDataFormat->mFormatType = SL_DATAFORMAT_NULL; 467 } else { 468 SLuint32 formatType = *(SLuint32 *)pFormat; 469 switch (formatType) { 470 471 case SL_DATAFORMAT_PCM: 472 pDataFormat->mPCM = *(SLDataFormat_PCM *)pFormat; 473 do { 474 475 // check the channel count 476 switch (pDataFormat->mPCM.numChannels) { 477 case 1: // mono 478 case 2: // stereo 479 break; 480 case 0: // unknown 481 result = SL_RESULT_PARAMETER_INVALID; 482 break; 483 default: // multi-channel 484 result = SL_RESULT_CONTENT_UNSUPPORTED; 485 break; 486 } 487 if (SL_RESULT_SUCCESS != result) { 488 SL_LOGE("numChannels=%u", (unsigned) pDataFormat->mPCM.numChannels); 489 break; 490 } 491 492 // check the sampling rate 493 switch (pDataFormat->mPCM.samplesPerSec) { 494 case SL_SAMPLINGRATE_8: 495 case SL_SAMPLINGRATE_11_025: 496 case SL_SAMPLINGRATE_12: 497 case SL_SAMPLINGRATE_16: 498 case SL_SAMPLINGRATE_22_05: 499 case SL_SAMPLINGRATE_24: 500 case SL_SAMPLINGRATE_32: 501 case SL_SAMPLINGRATE_44_1: 502 case SL_SAMPLINGRATE_48: 503 case SL_SAMPLINGRATE_64: 504 case SL_SAMPLINGRATE_88_2: 505 case SL_SAMPLINGRATE_96: 506 case SL_SAMPLINGRATE_192: 507 break; 508 case 0: 509 result = SL_RESULT_PARAMETER_INVALID; 510 break; 511 default: 512 result = SL_RESULT_CONTENT_UNSUPPORTED; 513 break; 514 } 515 if (SL_RESULT_SUCCESS != result) { 516 SL_LOGE("samplesPerSec=%u", (unsigned) pDataFormat->mPCM.samplesPerSec); 517 break; 518 } 519 520 // check the sample bit depth 521 switch (pDataFormat->mPCM.bitsPerSample) { 522 case SL_PCMSAMPLEFORMAT_FIXED_8: 523 case SL_PCMSAMPLEFORMAT_FIXED_16: 524 break; 525 case SL_PCMSAMPLEFORMAT_FIXED_20: 526 case SL_PCMSAMPLEFORMAT_FIXED_24: 527 case SL_PCMSAMPLEFORMAT_FIXED_28: 528 case SL_PCMSAMPLEFORMAT_FIXED_32: 529 result = SL_RESULT_CONTENT_UNSUPPORTED; 530 break; 531 default: 532 result = SL_RESULT_PARAMETER_INVALID; 533 break; 534 } 535 if (SL_RESULT_SUCCESS != result) { 536 SL_LOGE("bitsPerSample=%u", (unsigned) pDataFormat->mPCM.bitsPerSample); 537 break; 538 } 539 540 // check the container bit depth 541 switch (pDataFormat->mPCM.containerSize) { 542 case SL_PCMSAMPLEFORMAT_FIXED_8: 543 case SL_PCMSAMPLEFORMAT_FIXED_16: 544 if (pDataFormat->mPCM.containerSize != pDataFormat->mPCM.bitsPerSample) { 545 result = SL_RESULT_CONTENT_UNSUPPORTED; 546 } 547 break; 548 default: 549 result = SL_RESULT_CONTENT_UNSUPPORTED; 550 break; 551 } 552 if (SL_RESULT_SUCCESS != result) { 553 SL_LOGE("containerSize=%u", (unsigned) pDataFormat->mPCM.containerSize); 554 break; 555 } 556 557 // check the channel mask 558 switch (pDataFormat->mPCM.channelMask) { 559 case SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT: 560 if (2 != pDataFormat->mPCM.numChannels) { 561 result = SL_RESULT_PARAMETER_INVALID; 562 } 563 break; 564 case SL_SPEAKER_FRONT_LEFT: 565 case SL_SPEAKER_FRONT_RIGHT: 566 case SL_SPEAKER_FRONT_CENTER: 567 if (1 != pDataFormat->mPCM.numChannels) { 568 result = SL_RESULT_PARAMETER_INVALID; 569 } 570 break; 571 case 0: 572 pDataFormat->mPCM.channelMask = pDataFormat->mPCM.numChannels == 2 ? 573 SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT : SL_SPEAKER_FRONT_CENTER; 574 break; 575 default: 576 result = SL_RESULT_PARAMETER_INVALID; 577 break; 578 } 579 if (SL_RESULT_SUCCESS != result) { 580 SL_LOGE("channelMask=0x%lx numChannels=%lu", pDataFormat->mPCM.channelMask, 581 pDataFormat->mPCM.numChannels); 582 break; 583 } 584 585 // check the endianness / byte order 586 switch (pDataFormat->mPCM.endianness) { 587 case SL_BYTEORDER_LITTLEENDIAN: 588 case SL_BYTEORDER_BIGENDIAN: 589 break; 590 // native is proposed but not yet in spec 591 default: 592 result = SL_RESULT_PARAMETER_INVALID; 593 break; 594 } 595 if (SL_RESULT_SUCCESS != result) { 596 SL_LOGE("endianness=%u", (unsigned) pDataFormat->mPCM.endianness); 597 break; 598 } 599 600 // here if all checks passed successfully 601 602 } while(0); 603 break; 604 605 case SL_DATAFORMAT_MIME: 606 pDataFormat->mMIME = *(SLDataFormat_MIME *)pFormat; 607 if (NULL != pDataFormat->mMIME.mimeType) { 608 // NTH check address for validity 609 size_t len = strlen((const char *) pDataFormat->mMIME.mimeType); 610 SLchar *myMIME = (SLchar *) malloc(len + 1); 611 if (NULL == myMIME) { 612 result = SL_RESULT_MEMORY_FAILURE; 613 } else { 614 memcpy(myMIME, pDataFormat->mMIME.mimeType, len + 1); 615 // make sure MIME string was not modified asynchronously 616 if ('\0' != myMIME[len]) { 617 free(myMIME); 618 myMIME = NULL; 619 result = SL_RESULT_PRECONDITIONS_VIOLATED; 620 } 621 } 622 pDataFormat->mMIME.mimeType = myMIME; 623 } 624 break; 625 626 default: 627 result = SL_RESULT_PARAMETER_INVALID; 628 SL_LOGE("formatType=%u", (unsigned) formatType); 629 break; 630 631 } 632 633 // make sure format type was not modified asynchronously 634 if ((SL_RESULT_SUCCESS == result) && (formatType != pDataFormat->mFormatType)) { 635 result = SL_RESULT_PRECONDITIONS_VIOLATED; 636 } 637 638 } 639 640 return result; 641} 642 643 644/** \brief Check interface ID compatibility with respect to a particular data locator format */ 645 646SLresult checkSourceFormatVsInterfacesCompatibility(const DataLocatorFormat *pDataLocatorFormat, 647 SLuint32 numInterfaces, const SLInterfaceID *pInterfaceIds, 648 const SLboolean *pInterfaceRequired) { 649 // can't request SLSeekItf if data source is a buffer queue 650 // FIXME there are other invalid combinations -- see docs 651 SLuint32 i; 652 switch (pDataLocatorFormat->mLocator.mLocatorType) { 653 case SL_DATALOCATOR_BUFFERQUEUE: 654#ifdef ANDROID 655 case SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE: 656#endif 657 for (i = 0; i < numInterfaces; i++) { 658 // FIXME the == needs work 659 if (pInterfaceRequired[i] && (SL_IID_SEEK == pInterfaceIds[i])) { 660 SL_LOGE("can't request SL_IID_SEEK with a buffer queue data source"); 661 return SL_RESULT_FEATURE_UNSUPPORTED; 662 } 663 } 664 break; 665 default: 666 break; 667 } 668 return SL_RESULT_SUCCESS; 669} 670 671 672/** \brief Free the local deep copy of a data format */ 673 674static void freeDataFormat(DataFormat *pDataFormat) 675{ 676 switch (pDataFormat->mFormatType) { 677 case SL_DATAFORMAT_MIME: 678 if (NULL != pDataFormat->mMIME.mimeType) { 679 free(pDataFormat->mMIME.mimeType); 680 pDataFormat->mMIME.mimeType = NULL; 681 } 682 break; 683 default: 684 break; 685 } 686} 687 688 689/** \brief Check a data source and make local deep copy */ 690 691SLresult checkDataSource(const SLDataSource *pDataSrc, DataLocatorFormat *pDataLocatorFormat) 692{ 693 if (NULL == pDataSrc) { 694 SL_LOGE("pDataSrc NULL"); 695 return SL_RESULT_PARAMETER_INVALID; 696 } 697 SLDataSource myDataSrc = *pDataSrc; 698 SLresult result; 699 result = checkDataLocator(myDataSrc.pLocator, &pDataLocatorFormat->mLocator); 700 if (SL_RESULT_SUCCESS != result) { 701 return result; 702 } 703 switch (pDataLocatorFormat->mLocator.mLocatorType) { 704 705 case SL_DATALOCATOR_URI: 706 case SL_DATALOCATOR_ADDRESS: 707 case SL_DATALOCATOR_BUFFERQUEUE: 708 case SL_DATALOCATOR_MIDIBUFFERQUEUE: 709#ifdef ANDROID 710 case SL_DATALOCATOR_ANDROIDFD: 711 case SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE: 712#endif 713 result = checkDataFormat(myDataSrc.pFormat, &pDataLocatorFormat->mFormat); 714 if (SL_RESULT_SUCCESS != result) { 715 freeDataLocator(&pDataLocatorFormat->mLocator); 716 return result; 717 } 718 break; 719 720 case SL_DATALOCATOR_NULL: 721 case SL_DATALOCATOR_OUTPUTMIX: 722 default: 723 // invalid but fall through; the invalid locator will be caught later 724 SL_LOGE("mLocatorType=%u", (unsigned) pDataLocatorFormat->mLocator.mLocatorType); 725 // keep going 726 727 case SL_DATALOCATOR_IODEVICE: 728 // for these data locator types, ignore the pFormat as it might be uninitialized 729 pDataLocatorFormat->mFormat.mFormatType = SL_DATAFORMAT_NULL; 730 break; 731 } 732 733 pDataLocatorFormat->u.mSource.pLocator = &pDataLocatorFormat->mLocator; 734 pDataLocatorFormat->u.mSource.pFormat = &pDataLocatorFormat->mFormat; 735 return SL_RESULT_SUCCESS; 736} 737 738 739/** \brief Check a data sink and make local deep copy */ 740 741SLresult checkDataSink(const SLDataSink *pDataSink, DataLocatorFormat *pDataLocatorFormat, 742 SLuint32 objType) 743{ 744 if (NULL == pDataSink) { 745 SL_LOGE("pDataSink NULL"); 746 return SL_RESULT_PARAMETER_INVALID; 747 } 748 SLDataSink myDataSink = *pDataSink; 749 SLresult result; 750 result = checkDataLocator(myDataSink.pLocator, &pDataLocatorFormat->mLocator); 751 if (SL_RESULT_SUCCESS != result) { 752 return result; 753 } 754 switch (pDataLocatorFormat->mLocator.mLocatorType) { 755 756 case SL_DATALOCATOR_URI: 757 case SL_DATALOCATOR_ADDRESS: 758 result = checkDataFormat(myDataSink.pFormat, &pDataLocatorFormat->mFormat); 759 if (SL_RESULT_SUCCESS != result) { 760 freeDataLocator(&pDataLocatorFormat->mLocator); 761 return result; 762 } 763 break; 764 765 case SL_DATALOCATOR_BUFFERQUEUE: 766#ifdef ANDROID 767 case SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE: 768#endif 769 if (SL_OBJECTID_AUDIOPLAYER == objType) { 770 SL_LOGE("buffer queue can't be used as data sink for audio player"); 771 result = SL_RESULT_PARAMETER_INVALID; 772 } else if (SL_OBJECTID_AUDIORECORDER == objType) { 773#ifdef ANDROID 774 if (SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE != 775 pDataLocatorFormat->mLocator.mLocatorType) { 776 SL_LOGE("audio recorder source locator must be SL_DATALOCATOR_ANDROIDBUFFERQUEUE"); 777 result = SL_RESULT_PARAMETER_INVALID; 778 } else { 779 result = checkDataFormat(myDataSink.pFormat, &pDataLocatorFormat->mFormat); 780 } 781#else 782 SL_LOGE("mLocatorType=%u", (unsigned) pDataLocatorFormat->mLocator.mLocatorType); 783 result = SL_RESULT_PARAMETER_INVALID; 784#endif 785 } 786 if (SL_RESULT_SUCCESS != result) { 787 freeDataLocator(&pDataLocatorFormat->mLocator); 788 return result; 789 } 790 break; 791 792 case SL_DATALOCATOR_NULL: 793 case SL_DATALOCATOR_MIDIBUFFERQUEUE: 794 default: 795 // invalid but fall through; the invalid locator will be caught later 796 SL_LOGE("mLocatorType=%u", (unsigned) pDataLocatorFormat->mLocator.mLocatorType); 797 // keep going 798 799 case SL_DATALOCATOR_IODEVICE: 800 case SL_DATALOCATOR_OUTPUTMIX: 801 // for these data locator types, ignore the pFormat as it might be uninitialized 802 pDataLocatorFormat->mFormat.mFormatType = SL_DATAFORMAT_NULL; 803 break; 804 } 805 806 pDataLocatorFormat->u.mSink.pLocator = &pDataLocatorFormat->mLocator; 807 pDataLocatorFormat->u.mSink.pFormat = &pDataLocatorFormat->mFormat; 808 return SL_RESULT_SUCCESS; 809} 810 811 812/** \brief Free the local deep copy of a data locator format */ 813 814void freeDataLocatorFormat(DataLocatorFormat *dlf) 815{ 816 freeDataLocator(&dlf->mLocator); 817 freeDataFormat(&dlf->mFormat); 818} 819 820 821/* Interface initialization hooks */ 822 823extern void 824 I3DCommit_init(void *), 825 I3DDoppler_init(void *), 826 I3DGrouping_deinit(void *), 827 I3DGrouping_init(void *), 828 I3DLocation_init(void *), 829 I3DMacroscopic_init(void *), 830 I3DSource_init(void *), 831 IAndroidConfiguration_init(void *), 832 IAndroidEffectCapabilities_init(void *), 833 IAndroidEffectSend_init(void *), 834 IAndroidEffect_init(void *), 835 IAudioDecoderCapabilities_init(void *), 836 IAudioEncoderCapabilities_init(void *), 837 IAudioEncoder_init(void *), 838 IAudioIODeviceCapabilities_init(void *), 839 IBassBoost_init(void *), 840 IBufferQueue_init(void *), 841 IDeviceVolume_init(void *), 842 IDynamicInterfaceManagement_init(void *), 843 IDynamicSource_init(void *), 844 IEffectSend_init(void *), 845 IEngineCapabilities_init(void *), 846 IEngine_init(void *), 847 IEnvironmentalReverb_init(void *), 848 IEqualizer_init(void *), 849 ILEDArray_init(void *), 850 IMIDIMessage_init(void *), 851 IMIDIMuteSolo_init(void *), 852 IMIDITempo_init(void *), 853 IMIDITime_init(void *), 854 IMetadataExtraction_init(void *), 855 IMetadataTraversal_init(void *), 856 IMuteSolo_init(void *), 857 IObject_init(void *), 858 IOutputMixExt_init(void *), 859 IOutputMix_init(void *), 860 IPitch_init(void *), 861 IPlay_init(void *), 862 IPlaybackRate_init(void *), 863 IPrefetchStatus_init(void *), 864 IPresetReverb_init(void *), 865 IRatePitch_init(void *), 866 IRecord_init(void *), 867 ISeek_init(void *), 868 IThreadSync_init(void *), 869 IVibra_init(void *), 870 IVirtualizer_init(void *), 871 IVisualization_init(void *), 872 IVolume_init(void *); 873 874extern void 875 IObject_deinit(void *); 876 877#if !(USE_PROFILES & USE_PROFILES_MUSIC) 878#define IDynamicSource_init NULL 879#define IMetadataExtraction_init NULL 880#define IMetadataTraversal_init NULL 881#define IPlaybackRate_init NULL 882#define IVisualization_init NULL 883#endif 884 885#if !(USE_PROFILES & USE_PROFILES_GAME) 886#define I3DCommit_init NULL 887#define I3DDoppler_init NULL 888#define I3DGrouping_init NULL 889#define I3DLocation_init NULL 890#define I3DMacroscopic_init NULL 891#define I3DSource_init NULL 892#define IMIDIMessage_init NULL 893#define IMIDIMuteSolo_init NULL 894#define IMIDITempo_init NULL 895#define IMIDITime_init NULL 896#define IPitch_init NULL 897#define IRatePitch_init NULL 898#define I3DGrouping_deinit NULL 899#endif 900 901#if !(USE_PROFILES & USE_PROFILES_BASE) 902#define IAudioDecoderCapabilities_init NULL 903#define IAudioEncoderCapabilities_init NULL 904#define IAudioEncoder_init NULL 905#define IAudioIODeviceCapabilities_init NULL 906#define IDeviceVolume_init NULL 907#define IDynamicInterfaceManagement_init NULL 908#define IEngineCapabilities_init NULL 909#define IOutputMix_init NULL 910#define IThreadSync_init NULL 911#endif 912 913#if !(USE_PROFILES & USE_PROFILES_OPTIONAL) 914#define ILEDArray_init NULL 915#define IVibra_init NULL 916#endif 917 918#ifndef ANDROID 919#define IAndroidConfiguration_init NULL 920#define IAndroidEffect_init NULL 921#define IAndroidEffectCapabilities_init NULL 922#define IAndroidEffectSend_init NULL 923#endif 924 925#ifndef USE_OUTPUTMIXEXT 926#define IOutputMixExt_init NULL 927#endif 928 929 930/*static*/ const struct MPH_init MPH_init_table[MPH_MAX] = { 931 { /* MPH_3DCOMMIT, */ I3DCommit_init, NULL, NULL }, 932 { /* MPH_3DDOPPLER, */ I3DDoppler_init, NULL, NULL }, 933 { /* MPH_3DGROUPING, */ I3DGrouping_init, NULL, I3DGrouping_deinit }, 934 { /* MPH_3DLOCATION, */ I3DLocation_init, NULL, NULL }, 935 { /* MPH_3DMACROSCOPIC, */ I3DMacroscopic_init, NULL, NULL }, 936 { /* MPH_3DSOURCE, */ I3DSource_init, NULL, NULL }, 937 { /* MPH_AUDIODECODERCAPABILITIES, */ IAudioDecoderCapabilities_init, NULL, NULL }, 938 { /* MPH_AUDIOENCODER, */ IAudioEncoder_init, NULL, NULL }, 939 { /* MPH_AUDIOENCODERCAPABILITIES, */ IAudioEncoderCapabilities_init, NULL, NULL }, 940 { /* MPH_AUDIOIODEVICECAPABILITIES, */ IAudioIODeviceCapabilities_init, NULL, NULL }, 941 { /* MPH_BASSBOOST, */ IBassBoost_init, NULL, NULL }, 942 { /* MPH_BUFFERQUEUE, */ IBufferQueue_init, NULL, NULL }, 943 { /* MPH_DEVICEVOLUME, */ IDeviceVolume_init, NULL, NULL }, 944 { /* MPH_DYNAMICINTERFACEMANAGEMENT, */ IDynamicInterfaceManagement_init, NULL, NULL }, 945 { /* MPH_DYNAMICSOURCE, */ IDynamicSource_init, NULL, NULL }, 946 { /* MPH_EFFECTSEND, */ IEffectSend_init, NULL, NULL }, 947 { /* MPH_ENGINE, */ IEngine_init, NULL, NULL }, 948 { /* MPH_ENGINECAPABILITIES, */ IEngineCapabilities_init, NULL, NULL }, 949 { /* MPH_ENVIRONMENTALREVERB, */ IEnvironmentalReverb_init, NULL, NULL }, 950 { /* MPH_EQUALIZER, */ IEqualizer_init, NULL, NULL }, 951 { /* MPH_LED, */ ILEDArray_init, NULL, NULL }, 952 { /* MPH_METADATAEXTRACTION, */ IMetadataExtraction_init, NULL, NULL }, 953 { /* MPH_METADATATRAVERSAL, */ IMetadataTraversal_init, NULL, NULL }, 954 { /* MPH_MIDIMESSAGE, */ IMIDIMessage_init, NULL, NULL }, 955 { /* MPH_MIDITIME, */ IMIDITime_init, NULL, NULL }, 956 { /* MPH_MIDITEMPO, */ IMIDITempo_init, NULL, NULL }, 957 { /* MPH_MIDIMUTESOLO, */ IMIDIMuteSolo_init, NULL, NULL }, 958 { /* MPH_MUTESOLO, */ IMuteSolo_init, NULL, NULL }, 959 { /* MPH_NULL, */ NULL, NULL, NULL }, 960 { /* MPH_OBJECT, */ IObject_init, NULL, IObject_deinit }, 961 { /* MPH_OUTPUTMIX, */ IOutputMix_init, NULL, NULL }, 962 { /* MPH_PITCH, */ IPitch_init, NULL, NULL }, 963 { /* MPH_PLAY, */ IPlay_init, NULL, NULL }, 964 { /* MPH_PLAYBACKRATE, */ IPlaybackRate_init, NULL, NULL }, 965 { /* MPH_PREFETCHSTATUS, */ IPrefetchStatus_init, NULL, NULL }, 966 { /* MPH_PRESETREVERB, */ IPresetReverb_init, NULL, NULL }, 967 { /* MPH_RATEPITCH, */ IRatePitch_init, NULL, NULL }, 968 { /* MPH_RECORD, */ IRecord_init, NULL, NULL }, 969 { /* MPH_SEEK, */ ISeek_init, NULL, NULL }, 970 { /* MPH_THREADSYNC, */ IThreadSync_init, NULL, NULL }, 971 { /* MPH_VIBRA, */ IVibra_init, NULL, NULL }, 972 { /* MPH_VIRTUALIZER, */ IVirtualizer_init, NULL, NULL }, 973 { /* MPH_VISUALIZATION, */ IVisualization_init, NULL, NULL }, 974 { /* MPH_VOLUME, */ IVolume_init, NULL, NULL }, 975 { /* MPH_OUTPUTMIXEXT, */ IOutputMixExt_init, NULL, NULL }, 976 { /* MPH_ANDROIDEFFECT */ IAndroidEffect_init, NULL, NULL }, 977 { /* MPH_ANDROIDEFFECTCAPABILITIES */ IAndroidEffectCapabilities_init, NULL, NULL }, 978 { /* MPH_ANDROIDEFFECTSEND */ IAndroidEffectSend_init, NULL, NULL }, 979 { /* MPH_ANDROIDCONFIGURATION */ IAndroidConfiguration_init, NULL, NULL }, 980 { /* MPH_ANDROIDSIMPLEBUFFERQUEUE, */ IBufferQueue_init /* alias */, NULL, NULL } 981}; 982 983 984/** \brief Construct a new instance of the specified class, exposing selected interfaces */ 985 986IObject *construct(const ClassTable *class__, unsigned exposedMask, SLEngineItf engine) 987{ 988 IObject *this; 989 this = (IObject *) calloc(1, class__->mSize); 990 if (NULL != this) { 991 unsigned lossOfControlMask = 0; 992 // a NULL engine means we are constructing the engine 993 IEngine *thisEngine = (IEngine *) engine; 994 if (NULL == thisEngine) { 995 thisEngine = &((CEngine *) this)->mEngine; 996 } else { 997 interface_lock_exclusive(thisEngine); 998 if (MAX_INSTANCE <= thisEngine->mInstanceCount) { 999 SL_LOGE("Too many objects"); 1000 interface_unlock_exclusive(thisEngine); 1001 free(this); 1002 return NULL; 1003 } 1004 // pre-allocate a pending slot, but don't assign bit from mInstanceMask yet 1005 ++thisEngine->mInstanceCount; 1006 assert(((unsigned) ~0) != thisEngine->mInstanceMask); 1007 interface_unlock_exclusive(thisEngine); 1008 // const, no lock needed 1009 if (thisEngine->mLossOfControlGlobal) { 1010 lossOfControlMask = ~0; 1011 } 1012 } 1013 this->mLossOfControlMask = lossOfControlMask; 1014 this->mClass = class__; 1015 this->mEngine = thisEngine; 1016 const struct iid_vtable *x = class__->mInterfaces; 1017 SLuint8 *interfaceStateP = this->mInterfaceStates; 1018 SLuint32 index; 1019 for (index = 0; index < class__->mInterfaceCount; ++index, ++x, exposedMask >>= 1) { 1020 SLuint8 state; 1021 if (exposedMask & 1) { 1022 void *self = (char *) this + x->mOffset; 1023 // IObject does not have an mThis, so [1] is not always defined 1024 if (index) { 1025 ((IObject **) self)[1] = this; 1026 } 1027 VoidHook init = MPH_init_table[x->mMPH].mInit; 1028 // paranoid double-check for presence of an initialization hook 1029 if (NULL != init) { 1030 (*init)(self); 1031 } 1032 // IObject does not require a call to GetInterface 1033 if (index) { 1034 ((size_t *) self)[0] ^= ~0; 1035 } 1036 state = INTERFACE_EXPOSED; 1037 } else { 1038 state = INTERFACE_UNINITIALIZED; 1039 } 1040 *interfaceStateP++ = state; 1041 } 1042 // note that the new object is not yet published; creator must call IObject_Publish 1043 } 1044 return this; 1045} 1046 1047 1048/* Initial global entry points */ 1049 1050 1051/** \brief slCreateEngine Function */ 1052 1053SLresult SLAPIENTRY slCreateEngine(SLObjectItf *pEngine, SLuint32 numOptions, 1054 const SLEngineOption *pEngineOptions, SLuint32 numInterfaces, 1055 const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired) 1056{ 1057 SL_ENTER_GLOBAL 1058 1059 do { 1060 1061#ifdef ANDROID 1062 android::ProcessState::self()->startThreadPool(); 1063#ifndef USE_BACKPORT 1064 android::DataSource::RegisterDefaultSniffers(); 1065#endif 1066#endif 1067 1068 if (NULL == pEngine) { 1069 result = SL_RESULT_PARAMETER_INVALID; 1070 break; 1071 } 1072 *pEngine = NULL; 1073 1074 if ((0 < numOptions) && (NULL == pEngineOptions)) { 1075 SL_LOGE("numOptions=%lu and pEngineOptions=NULL", numOptions); 1076 result = SL_RESULT_PARAMETER_INVALID; 1077 break; 1078 } 1079 1080 // default values 1081 SLboolean threadSafe = SL_BOOLEAN_TRUE; 1082 SLboolean lossOfControlGlobal = SL_BOOLEAN_FALSE; 1083 1084 // process engine options 1085 SLuint32 i; 1086 const SLEngineOption *option = pEngineOptions; 1087 result = SL_RESULT_SUCCESS; 1088 for (i = 0; i < numOptions; ++i, ++option) { 1089 switch (option->feature) { 1090 case SL_ENGINEOPTION_THREADSAFE: 1091 threadSafe = SL_BOOLEAN_FALSE != (SLboolean) option->data; // normalize 1092 break; 1093 case SL_ENGINEOPTION_LOSSOFCONTROL: 1094 lossOfControlGlobal = SL_BOOLEAN_FALSE != (SLboolean) option->data; // normalize 1095 break; 1096 default: 1097 SL_LOGE("unknown engine option: feature=%lu data=%lu", 1098 option->feature, option->data); 1099 result = SL_RESULT_PARAMETER_INVALID; 1100 break; 1101 } 1102 } 1103 if (SL_RESULT_SUCCESS != result) { 1104 break; 1105 } 1106 1107 unsigned exposedMask; 1108 const ClassTable *pCEngine_class = objectIDtoClass(SL_OBJECTID_ENGINE); 1109 result = checkInterfaces(pCEngine_class, numInterfaces, 1110 pInterfaceIds, pInterfaceRequired, &exposedMask); 1111 if (SL_RESULT_SUCCESS != result) { 1112 break; 1113 } 1114 1115 CEngine *this = (CEngine *) construct(pCEngine_class, exposedMask, NULL); 1116 if (NULL == this) { 1117 result = SL_RESULT_MEMORY_FAILURE; 1118 break; 1119 } 1120 1121 this->mObject.mLossOfControlMask = lossOfControlGlobal ? ~0 : 0; 1122 this->mEngine.mLossOfControlGlobal = lossOfControlGlobal; 1123 this->mEngineCapabilities.mThreadSafe = threadSafe; 1124 *pEngine = &this->mObject.mItf; 1125 1126 } while(0); 1127 1128 SL_LEAVE_GLOBAL 1129} 1130 1131 1132/** \brief slQueryNumSupportedEngineInterfaces Function */ 1133 1134SLresult SLAPIENTRY slQueryNumSupportedEngineInterfaces(SLuint32 *pNumSupportedInterfaces) 1135{ 1136 SL_ENTER_GLOBAL 1137 1138 if (NULL == pNumSupportedInterfaces) { 1139 result = SL_RESULT_PARAMETER_INVALID; 1140 } else { 1141 const ClassTable *class__ = objectIDtoClass(SL_OBJECTID_ENGINE); 1142 assert(NULL != class__); 1143 SLuint32 count = 0; 1144 SLuint32 i; 1145 for (i = 0; i < class__->mInterfaceCount; ++i) { 1146 switch (class__->mInterfaces[i].mInterface) { 1147 case INTERFACE_IMPLICIT: 1148 case INTERFACE_EXPLICIT: 1149 case INTERFACE_DYNAMIC: 1150 ++count; 1151 break; 1152 case INTERFACE_UNAVAILABLE: 1153 break; 1154 default: 1155 assert(false); 1156 break; 1157 } 1158 } 1159 *pNumSupportedInterfaces = count; 1160 result = SL_RESULT_SUCCESS; 1161 } 1162 1163 SL_LEAVE_GLOBAL 1164} 1165 1166 1167/** \brief slQuerySupportedEngineInterfaces Function */ 1168 1169SLresult SLAPIENTRY slQuerySupportedEngineInterfaces(SLuint32 index, SLInterfaceID *pInterfaceId) 1170{ 1171 SL_ENTER_GLOBAL 1172 1173 if (NULL == pInterfaceId) { 1174 result = SL_RESULT_PARAMETER_INVALID; 1175 } else { 1176 *pInterfaceId = NULL; 1177 const ClassTable *class__ = objectIDtoClass(SL_OBJECTID_ENGINE); 1178 assert(NULL != class__); 1179 result = SL_RESULT_PARAMETER_INVALID; // will be reset later 1180 SLuint32 i; 1181 for (i = 0; i < class__->mInterfaceCount; ++i) { 1182 switch (class__->mInterfaces[i].mInterface) { 1183 case INTERFACE_IMPLICIT: 1184 case INTERFACE_EXPLICIT: 1185 case INTERFACE_DYNAMIC: 1186 break; 1187 case INTERFACE_UNAVAILABLE: 1188 continue; 1189 default: 1190 assert(false); 1191 break; 1192 } 1193 if (index == 0) { 1194 // The engine has no aliases, but if it did, this would return only the primary 1195 *pInterfaceId = &SL_IID_array[class__->mInterfaces[i].mMPH]; 1196 result = SL_RESULT_SUCCESS; 1197 break; 1198 } 1199 --index; 1200 } 1201 } 1202 1203 SL_LEAVE_GLOBAL 1204} 1205