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