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