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