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