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